diff options
Diffstat (limited to 'gerbview')
100 files changed, 28263 insertions, 0 deletions
diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt new file mode 100644 index 0000000..1404964 --- /dev/null +++ b/gerbview/CMakeLists.txt @@ -0,0 +1,190 @@ +# the map generation creates on Windows/gcc a lot of useless warnings +# so disable it on windows +if( WIN32 AND NOT CMAKE_CROSSCOMPILING ) + set( MAKE_LINK_MAPS false ) +else() + set( MAKE_LINK_MAPS true ) +endif() + +add_definitions(-DGERBVIEW) + +include_directories( BEFORE ${INC_BEFORE} ) +include_directories( + ../pcbnew + dialogs + ../3d-viewer + ../polygon + ${INC_AFTER} + ) + + +set( DIALOGS_SRCS + dialogs/gerbview_dialog_display_options_frame_base.cpp + dialogs/gerbview_dialog_display_options_frame.cpp + dialogs/dialog_layers_select_to_pcb_base.cpp + dialogs/dialog_print_using_printer.cpp + dialogs/dialog_print_using_printer_base.cpp + dialogs/dialog_select_one_pcb_layer.cpp + dialogs/dialog_show_page_borders.cpp + dialogs/dialog_show_page_borders_base.cpp + ) + +set( GERBVIEW_SRCS + block.cpp + class_am_param.cpp + class_aperture_macro.cpp + class_DCodeSelectionbox.cpp + class_gbr_screen.cpp + class_gbr_layout.cpp + class_GERBER.cpp + class_gerber_draw_item.cpp + class_gerbview_layer_widget.cpp + class_gbr_layer_box_selector.cpp + class_X2_gerber_attributes.cpp + controle.cpp + dcode.cpp + draw_gerber_screen.cpp + events_called_functions.cpp + excellon_read_drill_file.cpp + export_to_pcbnew.cpp + files.cpp + gerbview_config.cpp + gerbview_frame.cpp + hotkeys.cpp + init_gbr_drawlayers.cpp + locate.cpp + menubar.cpp + onleftclick.cpp + onrightclick.cpp + pcbplot.cpp + printout_control.cpp + readgerb.cpp + rs274_read_XY_and_IJ_coordinates.cpp + rs274d.cpp + rs274x.cpp + select_layers_to_pcb.cpp + toolbars_gerber.cpp + ) + +set( GERBVIEW_EXTRA_SRCS + ../common/base_screen.cpp + ../common/base_units.cpp + ../common/eda_text.cpp + ../common/class_layer_box_selector.cpp + ../common/class_page_info.cpp + ../pcbnew/layer_widget.cpp +) + +if( MINGW ) + # GERBVIEW_RESOURCES variable is set by the macro. + mingw_resource_compiler( gerbview ) +else() + set( GERBVIEW_RESOURCES gerbview.rc ) +endif() + +if( APPLE ) + # setup bundle + set( GERBVIEW_RESOURCES gerbview.icns gerbview_doc.icns ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/gerbview.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/gerbview_doc.icns" PROPERTIES + MACOSX_PACKAGE_LOCATION Resources + ) + set( MACOSX_BUNDLE_ICON_FILE gerbview.icns ) + set( MACOSX_BUNDLE_GUI_IDENTIFIER org.kicad-pcb.kicad ) + set( MACOSX_BUNDLE_NAME gerbview ) +endif() + +add_executable( gerbview WIN32 MACOSX_BUNDLE + ../common/single_top.cpp + ../common/pgm_base.cpp + ${GERBVIEW_RESOURCES} + ) +set_source_files_properties( ../common/single_top.cpp PROPERTIES + COMPILE_DEFINITIONS "TOP_FRAME=FRAME_GERBER;BUILD_KIWAY_DLL" + ) +target_link_libraries( gerbview + #singletop # replaces common, giving us restrictive control and link warnings. + # There's way too much crap coming in from common yet. + common + bitmaps + ${wxWidgets_LIBRARIES} + ) + +if( MAKE_LINK_MAPS ) + set_target_properties( gerbview PROPERTIES + LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=gerbview.map" ) +endif() + +# the main gerbview program, in DSO form. +add_library( gerbview_kiface MODULE + gerbview.cpp + ${GERBVIEW_SRCS} + ${DIALOGS_SRCS} + ${GERBVIEW_EXTRA_SRCS} + ) +set_target_properties( gerbview_kiface PROPERTIES + OUTPUT_NAME gerbview + PREFIX ${KIFACE_PREFIX} + SUFFIX ${KIFACE_SUFFIX} + ) +target_link_libraries( gerbview_kiface + common + polygon + bitmaps + gal + ${wxWidgets_LIBRARIES} + ${GDI_PLUS_LIBRARIES} + ) +set_source_files_properties( gerbview.cpp PROPERTIES + # The KIFACE is in gerbview.cpp, export it: + COMPILE_DEFINITIONS "BUILD_KIWAY_DLL;COMPILING_DLL" + ) + +if( MAKE_LINK_MAPS ) + set_target_properties( gerbview_kiface PROPERTIES + LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=_gerbview.kiface.map" ) +endif() + +# if building gerbview, then also build gerbview_kiface if out of date. +add_dependencies( gerbview gerbview_kiface ) + +# these 2 binaries are a matched set, keep them together +if( APPLE ) + set_target_properties( gerbview PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + ) + + # puts binaries into the *.app bundle while linking + set_target_properties( gerbview_kiface PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${OSX_BUNDLE_BUILD_KIFACE_DIR} + ) + # put individual bundle outside of main bundle as a first step + # will be pulled into the main bundle when creating main bundle + install( TARGETS gerbview + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) + install( CODE " + # override default embedded path settings + ${OSX_BUNDLE_OVERRIDE_PATHS} + + # do all the work + include( BundleUtilities ) + fixup_bundle( ${KICAD_BIN}/gerbview.app/Contents/MacOS/gerbview + \"\" + \"\" + ) + " COMPONENT Runtime + ) +else() + install( TARGETS gerbview + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) + install( TARGETS gerbview_kiface + DESTINATION ${KICAD_BIN} + COMPONENT binary + ) +endif() diff --git a/gerbview/Info.plist b/gerbview/Info.plist new file mode 100644 index 0000000..f3dbf5c --- /dev/null +++ b/gerbview/Info.plist @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeExtensions</key> + <array> + <string>pen</string> + <string>gba</string> + <string>gbr</string> + <string>gbx</string> + <string>gbo</string> + <string>gbl</string> + <string>gtl</string> + <string>gto</string> + <string>gta</string> + <string>gbp</string> + <string>gbp</string> + <string>gbs</string> + <string>gts</string> + <string>gtp</string> + <string>gbx</string> + <string>lgr</string> + <string>ger</string> + <string>pho</string> + <string>drl</string> + </array> + + <key>CFBundleTypeIconFile</key> <string>gerbview_doc.icns</string> + <key>CFBundleTypeName</key> <string>gerbview document</string> + <key>LSHandlerRank</key> <string>Default</string> + <key>CFBundleTypeRole</key> <string>Viewer</string> + </dict> + </array> + + <key>CFBundleDevelopmentRegion</key> <string>English</string> + <key>CFBundleExecutable</key> <string>gerbview</string> + <key>CFBundleGetInfoString</key> <string></string> + <key>CFBundleIconFile</key> <string>gerbview.icns</string> + <key>CFBundleIdentifier</key> <string>org.kicad-pcb.gerbview</string> + <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> + <key>CFBundleLongVersionString</key> <string></string> + <key>CFBundleName</key> <string>GerbView</string> + <key>CFBundlePackageType</key> <string>APPL</string> + <key>CFBundleShortVersionString</key> <string></string> + <key>CFBundleSignature</key> <string>????</string> + <key>CFBundleVersion</key> <string></string> + <key>CSResourcesFileMapped</key> <true/> + <key>LSRequiresCarbon</key> <true/> + <key>NSHumanReadableCopyright</key> <string></string> + <key>NSHighResolutionCapable</key> <string>True</string> +</dict> +</plist> diff --git a/gerbview/block.cpp b/gerbview/block.cpp new file mode 100644 index 0000000..1218322 --- /dev/null +++ b/gerbview/block.cpp @@ -0,0 +1,221 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 <Jean-Pierre Charras> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview/block.cpp + * @brief Block operations: displacement. + */ + + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <gr_basic.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> + +#include <wx/debug.h> + +#define BLOCK_COLOR BROWN + + +static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, + bool erase ); + + +int GERBVIEW_FRAME::BlockCommand( int key ) +{ + int cmd = 0; + + switch( key ) + { + default: + cmd = key & 0x255; + break; + + case 0: + cmd = BLOCK_MOVE; + break; + + case GR_KB_SHIFT: + case GR_KB_CTRL: + case GR_KB_SHIFTCTRL: + case GR_KB_ALT: + break; + + case MOUSE_MIDDLE: + cmd = BLOCK_ZOOM; + break; + } + + return cmd; +} + + +void GERBVIEW_FRAME::HandleBlockPlace( wxDC* DC ) +{ + wxASSERT( m_canvas->IsMouseCaptured() ); + + GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_STOP ); + + switch( GetScreen()->m_BlockLocate.GetCommand() ) + { + case BLOCK_MOVE: /* Move */ + if( m_canvas->IsMouseCaptured() ) + m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + + Block_Move( DC ); + GetScreen()->m_BlockLocate.ClearItemsList(); + break; + + default: + wxFAIL_MSG( wxT("HandleBlockPlace: Unexpected block command") ); + break; + } + + m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false ); + GetScreen()->SetModify(); + GetScreen()->ClearBlockCommand(); + + wxASSERT( GetScreen()->m_BlockLocate.GetCount() == 0 ); + + DisplayToolMsg( wxEmptyString ); +} + + +bool GERBVIEW_FRAME::HandleBlockEnd( wxDC* DC ) +{ + bool nextcmd = false; + bool zoom_command = false; + + if( m_canvas->IsMouseCaptured() ) + + switch( GetScreen()->m_BlockLocate.GetCommand() ) + { + case BLOCK_MOVE: /* Move */ + GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE ); + nextcmd = true; + m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); + m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + break; + + case BLOCK_ZOOM: /* Window Zoom */ + zoom_command = true; + break; + + default: + wxFAIL_MSG( wxT("HandleBlockEnd: Unexpected block command") ); + break; + } + + if( ! nextcmd ) + { + GetScreen()->ClearBlockCommand(); + m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, + false ); + } + + if( zoom_command ) + Window_Zoom( GetScreen()->m_BlockLocate ); + + return nextcmd ; +} + + +/* Traces the outline of the block structures of a repositioning move + */ +static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPositon, + bool aErase ) +{ + BASE_SCREEN* screen = aPanel->GetScreen(); + + EDA_COLOR_T Color = YELLOW; + + if( aErase ) + { + screen->m_BlockLocate.Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, Color ); + + if( screen->m_BlockLocate.GetMoveVector().x|| screen->m_BlockLocate.GetMoveVector().y ) + { + screen->m_BlockLocate.Draw( aPanel, + aDC, + screen->m_BlockLocate.GetMoveVector(), + g_XorMode, + Color ); + } + } + + if( screen->m_BlockLocate.GetState() != STATE_BLOCK_STOP ) + { + const wxPoint& cross_hair = aPanel->GetParent()->GetCrossHairPosition(); + + screen->m_BlockLocate.SetMoveVector( + wxPoint( cross_hair.x - screen->m_BlockLocate.GetRight(), + cross_hair.y - screen->m_BlockLocate.GetBottom() ) ); + } + + screen->m_BlockLocate.Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, Color ); + + if( screen->m_BlockLocate.GetMoveVector().x || screen->m_BlockLocate.GetMoveVector().y ) + { + screen->m_BlockLocate.Draw( aPanel, + aDC, + screen->m_BlockLocate.GetMoveVector(), + g_XorMode, + Color ); + } +} + + +void GERBVIEW_FRAME::Block_Move( wxDC* DC ) +{ + wxPoint delta; + wxPoint oldpos; + + oldpos = GetCrossHairPosition(); + m_canvas->SetMouseCaptureCallback( NULL ); + + SetCrossHairPosition( oldpos ); + m_canvas->MoveCursorToCrossHair(); + GetScreen()->SetModify(); + GetScreen()->m_BlockLocate.Normalize(); + + /* Calculate displacement vectors. */ + delta = GetScreen()->m_BlockLocate.GetMoveVector(); + + /* Move items in block */ + for( GERBER_DRAW_ITEM* item = GetItemsList(); item; item = item->Next() ) + { + GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item; + + if( gerb_item->HitTest( GetScreen()->m_BlockLocate ) ) + gerb_item->MoveAB( delta ); + } + + m_canvas->Refresh( true ); +} diff --git a/gerbview/class_DCodeSelectionbox.cpp b/gerbview/class_DCodeSelectionbox.cpp new file mode 100644 index 0000000..2d13596 --- /dev/null +++ b/gerbview/class_DCodeSelectionbox.cpp @@ -0,0 +1,84 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <pgm_base.h> +#include <wxstruct.h> +#include <class_drawpanel.h> +#include <gerbview.h> +#include <dcode.h> + +#include <class_DCodeSelectionbox.h> + +/*******************************************/ +/* Helper class for displaying DCodes list */ +/*******************************************/ + +DCODE_SELECTION_BOX::DCODE_SELECTION_BOX( wxAuiToolBar* aParent, wxWindowID aId, + const wxPoint& aLocation, const wxSize& aSize, + const wxArrayString& aChoices ) : + wxComboBox( aParent, aId, wxEmptyString, aLocation, aSize, 0, NULL, wxCB_READONLY ) +{ + m_dcodeList = &aChoices; + // Append aChoices here is by far faster than use aChoices inside + // the wxComboBox constructor + Append(aChoices); +} + + +DCODE_SELECTION_BOX::~DCODE_SELECTION_BOX() +{ +} + + +int DCODE_SELECTION_BOX::GetSelectedDCodeId() +{ + int ii = GetSelection(); + + if( ii > 0 ) + { + wxString msg = (*m_dcodeList)[ii].AfterFirst( wxChar( ' ' ) ); + long id; + msg.ToLong(&id); + return id; + } + + return -1; +} + + +/* SetDCodeSelection + * aDCodeId = the DCode Id to select or -1 to select "no dcode" + */ +void DCODE_SELECTION_BOX::SetDCodeSelection( int aDCodeId ) +{ + if( aDCodeId > LAST_DCODE ) + aDCodeId = LAST_DCODE; + + int index = 0; + if( aDCodeId >= FIRST_DCODE ) + index = aDCodeId - FIRST_DCODE + 1; + + SetSelection(index); +} diff --git a/gerbview/class_DCodeSelectionbox.h b/gerbview/class_DCodeSelectionbox.h new file mode 100644 index 0000000..d65578b --- /dev/null +++ b/gerbview/class_DCodeSelectionbox.h @@ -0,0 +1,58 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// file class_DCodeSelectionbox.h + +#ifndef CLASS_DCODESELECTIONBOX_H +#define CLASS_DCODESELECTIONBOX_H + +/* helper class to display a DCode list and select a DCode id. + */ + +// Define event type for DCODE_SELECTION_BOX +#define EVT_SELECT_DCODE EVT_COMBOBOX + +class DCODE_SELECTION_BOX : public wxComboBox +{ +private: + const wxArrayString* m_dcodeList; + +public: DCODE_SELECTION_BOX( wxAuiToolBar* aParent, wxWindowID aId, + const wxPoint& aLocation, const wxSize& aSize, + const wxArrayString& aChoices); + ~DCODE_SELECTION_BOX(); + + /** + * Function GetSelectedDCodeId + * @return the current selected DCode Id or -1 if no dcode + */ + int GetSelectedDCodeId(); + /** + * Function SetDCodeSelection + * @param aDCodeId = the DCode Id to select or -1 to select "no dcode" + */ + void SetDCodeSelection( int aDCodeId ); +}; + +#endif //CLASS_DCODESELECTIONBOX_H diff --git a/gerbview/class_GERBER.cpp b/gerbview/class_GERBER.cpp new file mode 100644 index 0000000..59d7615 --- /dev/null +++ b/gerbview/class_GERBER.cpp @@ -0,0 +1,557 @@ +/** + * @file class_GERBER.cpp + * a GERBER class handle for a given layer info about used D_CODES and how the layer is drawn + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2013 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <macros.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_GERBER.h> +#include <class_X2_gerber_attributes.h> + +#include <algorithm> + + +/** + * Function scaletoIU + * converts a distance given in floating point to our internal units + */ +extern int scaletoIU( double aCoord, bool isMetric ); // defined it rs274d_read_XY_and_IJ_coordiantes.cpp + +/* Format Gerber: NOTES: + * Tools and D_CODES + * tool number (identification of shapes) + * 1 to 999 + * + * D_CODES: + * D01 ... D9 = action codes: + * D01 = activating light (lower pen) when di placement + * D02 = light extinction (lift pen) when di placement + * D03 Flash + * D09 = VAPE Flash + * D10 ... = Indentification Tool (Opening) + * + * For tools: + * DCode min = D10 + * DCode max = 999 + */ + + +GERBER_LAYER::GERBER_LAYER() +{ + ResetDefaultValues(); +} + + +GERBER_LAYER::~GERBER_LAYER() +{ +} + + +void GERBER_LAYER::ResetDefaultValues() +{ + m_LayerName = wxT( "no name" ); // Layer name from the LN command + m_LayerNegative = false; // true = Negative Layer + m_StepForRepeat.x = m_StepForRepeat.y = 0; // X and Y offsets for Step and Repeat command + m_XRepeatCount = 1; // The repeat count on X axis + m_YRepeatCount = 1; // The repeat count on Y axis + m_StepForRepeatMetric = false; // false = Inches, true = metric +} + + +GERBER_IMAGE::GERBER_IMAGE( GERBVIEW_FRAME* aParent, int aLayer ) +{ + m_Parent = aParent; + m_GraphicLayer = aLayer; // Graphic layer Number + + m_Selected_Tool = FIRST_DCODE; + m_FileFunction = NULL; // file function parameters + + ResetDefaultValues(); + + for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ ) + m_Aperture_List[ii] = 0; +} + + +GERBER_IMAGE::~GERBER_IMAGE() +{ + for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ ) + { + delete m_Aperture_List[ii]; + } + + delete m_FileFunction; +} + +/* + * Function GetItemsList + * returns the first GERBER_DRAW_ITEM * item of the items list + */ +GERBER_DRAW_ITEM * GERBER_IMAGE::GetItemsList() +{ + return m_Parent->GetItemsList(); +} + +D_CODE* GERBER_IMAGE::GetDCODE( int aDCODE, bool create ) +{ + unsigned ndx = aDCODE - FIRST_DCODE; + + if( ndx < (unsigned) DIM( m_Aperture_List ) ) + { + // lazily create the D_CODE if it does not exist. + if( create ) + { + if( m_Aperture_List[ndx] == NULL ) + m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE ); + } + + return m_Aperture_List[ndx]; + } + return NULL; +} + + +APERTURE_MACRO* GERBER_IMAGE::FindApertureMacro( const APERTURE_MACRO& aLookup ) +{ + APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup ); + + if( iter != m_aperture_macros.end() ) + { + APERTURE_MACRO* pam = (APERTURE_MACRO*) &(*iter); + return pam; + } + + return NULL; // not found +} + + +void GERBER_IMAGE::ResetDefaultValues() +{ + m_InUse = false; + m_GBRLayerParams.ResetDefaultValues(); + m_FileName.Empty(); + m_ImageName = wxT( "no name" ); // Image name from the IN command + m_ImageNegative = false; // true = Negative image + m_IsX2_file = false; // true only if a %TF, %TA or %TD command + delete m_FileFunction; // file function parameters + m_FileFunction = NULL; + m_MD5_value.Empty(); // MD5 value found in a %TF.MD5 command + m_PartString.Empty(); // string found in a %TF.Part command + m_hasNegativeItems = -1; // set to uninitialized + m_ImageJustifyOffset = wxPoint(0,0); // Image justify Offset + 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_Relative = false; // false = absolute Coord, + // true = relative Coord + m_NoTrailingZeros = false; // true: trailing zeros deleted + m_DecimalFormat = false; // true: use floating point notations for coordinates + m_ImageOffset.x = m_ImageOffset.y = 0; // Coord Offset, from IO command + m_ImageRotation = 0; // Allowed 0, 90, 180, 270 (in degree) + m_LocalRotation = 0.0; // Layer totation from RO command (in 0.1 degree) + m_Offset.x = 0; + m_Offset.y = 0; // Coord Offset, from OF command + m_Scale.x = m_Scale.y = 1.0; // scale (A and B) this layer + m_MirrorA = false; // true: miror / axe A (default = X) + m_MirrorB = false; // true: miror / axe B (default = Y) + m_SwapAxis = false; // false if A = X, B = Y; true if A =Y, B = Y + m_Has_DCode = false; // true = DCodes in file + // false = no DCode-> + // search for separate DCode file + m_FmtScale.x = m_FmtScale.y = 4; // Initialize default format to 3.4 => 4 + m_FmtLen.x = m_FmtLen.y = 3 + 4; // Initialize default format len = 3+4 + + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ. + m_360Arc_enbl = false; // 360 deg circular + // interpolation disable + m_Current_Tool = 0; // Current Dcode selected + m_CommandState = 0; // State of the current command + m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord + m_PreviousPos.x = m_PreviousPos.y = 0; // last specified coord + m_IJPos.x = m_IJPos.y = 0; // current centre coord for + // plot arcs & circles + m_Current_File = NULL; // Gerber file to read + m_FilesPtr = 0; + m_PolygonFillMode = false; + m_PolygonFillModeState = 0; + m_Selected_Tool = FIRST_DCODE; + m_Last_Pen_Command = 0; + m_Exposure = false; + + for( unsigned ii = 0; ii < DIM( m_FilesList ); ii++ ) + m_FilesList[ii] = NULL; +} + +/* Function HasNegativeItems + * return true if at least one item must be drawn in background color + * used to optimize screen refresh + */ +bool GERBER_IMAGE::HasNegativeItems() +{ + if( m_hasNegativeItems < 0 ) // negative items are not yet searched: find them if any + { + if( m_ImageNegative ) // A negative layer is expected having always negative objects. + m_hasNegativeItems = 1; + else + { + m_hasNegativeItems = 0; + for( GERBER_DRAW_ITEM* item = GetItemsList(); item; item = item->Next() ) + { + if( item->GetLayer() != m_GraphicLayer ) + continue; + if( item->HasNegativeItems() ) + { + m_hasNegativeItems = 1; + break; + } + } + } + } + return m_hasNegativeItems == 1; +} + +int GERBER_IMAGE::UsedDcodeNumber() +{ + int count = 0; + + for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ ) + { + if( m_Aperture_List[ii] ) + if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined ) + ++count; + } + + return count; +} + + +void GERBER_IMAGE::InitToolTable() +{ + for( int count = 0; count < TOOLS_MAX_COUNT; count++ ) + { + if( m_Aperture_List[count] == NULL ) + continue; + + m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE; + m_Aperture_List[count]->Clear_D_CODE_Data(); + } + + m_aperture_macros.clear(); +} + + +/** + * Function ReportMessage + * Add a message (a string) in message list + * for instance when reading a Gerber file + * @param aMessage = the straing to add in list + */ +void GERBER_IMAGE::ReportMessage( const wxString aMessage ) +{ + m_Parent->ReportMessage( aMessage ); +} + + +/** + * Function ClearMessageList + * Clear the message list + * Call it before reading a Gerber file + */ +void GERBER_IMAGE::ClearMessageList() +{ + m_Parent->ClearMessageList(); +} + + +/** + * Function StepAndRepeatItem + * Gerber format has a command Step an Repeat + * This function must be called when reading a gerber file and + * after creating a new gerber item that must be repeated + * (i.e when m_XRepeatCount or m_YRepeatCount are > 1) + * @param aItem = the item to repeat + */ +void GERBER_IMAGE::StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem ) +{ + if( GetLayerParams().m_XRepeatCount < 2 && + GetLayerParams().m_YRepeatCount < 2 ) + return; // Nothing to repeat + // Duplicate item: + wxString msg; + for( int ii = 0; ii < GetLayerParams().m_XRepeatCount; ii++ ) + { + for( int jj = 0; jj < GetLayerParams().m_YRepeatCount; jj++ ) + { + // the first gerber item already exists (this is the template) + // create duplicate only if ii or jj > 0 + if( jj == 0 && ii == 0 ) + continue; + GERBER_DRAW_ITEM* dupItem = new GERBER_DRAW_ITEM( aItem ); + wxPoint move_vector; + move_vector.x = scaletoIU( ii * GetLayerParams().m_StepForRepeat.x, + GetLayerParams().m_StepForRepeatMetric ); + move_vector.y = scaletoIU( jj * GetLayerParams().m_StepForRepeat.y, + GetLayerParams().m_StepForRepeatMetric ); + dupItem->MoveXY( move_vector ); + m_Parent->GetGerberLayout()->m_Drawings.Append( dupItem ); + } + } +} + + +/** + * Function DisplayImageInfo + * has knowledge about the frame and how and where to put status information + * about this object into the frame's message panel. + * Display info about Image Parameters. + * These parameters are valid for the entire file, and must set only once + * (If more than once, only the last value is used) + */ +void GERBER_IMAGE::DisplayImageInfo( void ) +{ + wxString msg; + + m_Parent->ClearMsgPanel(); + + // Display Image name (Image specific) + m_Parent->AppendMsgPanel( _( "Image name" ), m_ImageName, CYAN ); + + // Display graphic layer number used to draw this Image + // (not a Gerber parameter but is also image specific) + msg.Printf( wxT( "%d" ), m_GraphicLayer + 1 ); + m_Parent->AppendMsgPanel( _( "Graphic layer" ), msg, BROWN ); + + // Display Image rotation (Image specific) + msg.Printf( wxT( "%d" ), m_ImageRotation ); + m_Parent->AppendMsgPanel( _( "Img Rot." ), msg, CYAN ); + + // Display Image polarity (Image specific) + msg = m_ImageNegative ? _("Negative") : _("Normal"); + m_Parent->AppendMsgPanel( _( "Polarity" ), msg, BROWN ); + + // Display Image justification and offset for justification (Image specific) + msg = m_ImageJustifyXCenter ? _("Center") : _("Normal"); + m_Parent->AppendMsgPanel( _( "X Justify" ), msg, DARKRED ); + + msg = m_ImageJustifyYCenter ? _("Center") : _("Normal"); + m_Parent->AppendMsgPanel( _( "Y Justify" ), msg, DARKRED ); + + if( g_UserUnit == INCHES ) + msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x/10000, + (double) m_ImageJustifyOffset.y/10000 ); + else + msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x*2.54/1000, + (double) m_ImageJustifyOffset.y*2.54/1000 ); + m_Parent->AppendMsgPanel( _( "Image Justify Offset" ), msg, DARKRED ); +} + +// GERBER_IMAGE_LIST is a helper class to handle a list of GERBER_IMAGE files +GERBER_IMAGE_LIST::GERBER_IMAGE_LIST() +{ + m_GERBER_List.reserve( GERBER_DRAWLAYERS_COUNT ); + + for( unsigned layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) + m_GERBER_List.push_back( NULL ); +} + +GERBER_IMAGE_LIST::~GERBER_IMAGE_LIST() +{ + ClearList(); + + for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer ) + { + delete m_GERBER_List[layer]; + m_GERBER_List[layer] = NULL; + } +} + +GERBER_IMAGE* GERBER_IMAGE_LIST::GetGbrImage( int aIdx ) +{ + if( (unsigned)aIdx < m_GERBER_List.size() ) + return m_GERBER_List[aIdx]; + + return NULL; +} + +/** + * creates a new, empty GERBER_IMAGE* at index aIdx + * or at the first free location if aIdx < 0 + * @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) + * @return true if the index used, or -1 if no room to add image + */ +int GERBER_IMAGE_LIST::AddGbrImage( GERBER_IMAGE* aGbrImage, int aIdx ) +{ + int idx = aIdx; + + if( idx < 0 ) + { + for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ ) + { + if( !IsUsed( idx ) ) + break; + } + } + + if( idx >= (int)m_GERBER_List.size() ) + return -1; // No room + + m_GERBER_List[idx] = aGbrImage; + + return idx; +} + + +// remove all loaded data in list, but do not delete empty images +// (can be reused) +void GERBER_IMAGE_LIST::ClearList() +{ + for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer ) + ClearImage( layer ); +} + +// remove the loaded data of image aIdx, but do not delete it +void GERBER_IMAGE_LIST::ClearImage( int aIdx ) +{ + if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() && m_GERBER_List[aIdx] ) + { + m_GERBER_List[aIdx]->InitToolTable(); + m_GERBER_List[aIdx]->ResetDefaultValues(); + m_GERBER_List[aIdx]->m_InUse = false; + } +} + +// Build a name for image aIdx which can be used in layers manager +const wxString GERBER_IMAGE_LIST::GetDisplayName( int aIdx ) +{ + wxString name; + + GERBER_IMAGE* gerber = NULL; + + if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() ) + gerber = m_GERBER_List[aIdx]; + + if( gerber && IsUsed(aIdx ) ) + { + if( gerber->m_FileFunction ) + { + if( gerber->m_FileFunction->IsCopper() ) + { + name.Printf( _( "Layer %d (%s, %s, %s)" ), aIdx + 1, + GetChars( gerber->m_FileFunction->GetFileType() ), + GetChars( gerber->m_FileFunction->GetBrdLayerId() ), + GetChars( gerber->m_FileFunction->GetBrdLayerSide() ) ); + } + else + { + name.Printf( _( "Layer %d (%s, %s)" ), aIdx + 1, + GetChars( gerber->m_FileFunction->GetFileType() ), + GetChars( gerber->m_FileFunction->GetBrdLayerId() ) ); + } + } + else + name.Printf( _( "Layer %d *" ), aIdx + 1 ); + } + else + name.Printf( _( "Layer %d" ), aIdx + 1 ); + + return name; +} + +// return true if image is used (loaded and not cleared) +bool GERBER_IMAGE_LIST::IsUsed( int aIdx ) +{ + if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() ) + return m_GERBER_List[aIdx] != NULL && m_GERBER_List[aIdx]->m_InUse; + + return false; +} + +// Helper function, for std::sort. +// Sort loaded images by Z order priority, if they have the X2 FileFormat info +// returns true if the first argument (ref) is ordered before the second (test). +static bool sortZorder( const GERBER_IMAGE* const& ref, const GERBER_IMAGE* const& test ) +{ + if( !ref && !test ) + return false; // do not change order: no criteria to sort items + + if( !ref || !ref->m_InUse ) + return false; // Not used: ref ordered after + + if( !test || !test->m_InUse ) + return true; // Not used: ref ordered before + + if( !ref->m_FileFunction && !test->m_FileFunction ) + return false; // do not change order: no criteria to sort items + + if( !ref->m_FileFunction ) + return false; + + if( !test->m_FileFunction ) + return true; + + if( ref->m_FileFunction->GetZOrder() != test->m_FileFunction->GetZOrder() ) + return ref->m_FileFunction->GetZOrder() > test->m_FileFunction->GetZOrder(); + + return ref->m_FileFunction->GetZSubOrder() > test->m_FileFunction->GetZSubOrder(); +} + +void GERBER_IMAGE_LIST::SortImagesByZOrder( GERBER_DRAW_ITEM* aDrawList ) +{ + std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortZorder ); + + // The image order has changed. + // Graphic layer numbering must be updated to match the widgets layer order + + // Store the old/new graphic layer info: + std::map <int, int> tab_lyr; + + for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer ) + { + if( m_GERBER_List[layer] ) + { + tab_lyr[m_GERBER_List[layer]->m_GraphicLayer] = layer; + m_GERBER_List[layer]->m_GraphicLayer = layer ; + } + } + + // update the graphic layer in items to draw + for( GERBER_DRAW_ITEM* item = aDrawList; item; item = item->Next() ) + { + int layer = item->GetLayer(); + item->SetLayer( tab_lyr[layer] ); + } +} + + +// The global image list: +GERBER_IMAGE_LIST g_GERBER_List; diff --git a/gerbview/class_GERBER.h b/gerbview/class_GERBER.h new file mode 100644 index 0000000..1f72c1c --- /dev/null +++ b/gerbview/class_GERBER.h @@ -0,0 +1,378 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2013 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _CLASS_GERBER_H_ +#define _CLASS_GERBER_H_ + +#include <vector> +#include <set> + +#include <dcode.h> +#include <class_gerber_draw_item.h> +#include <class_aperture_macro.h> + +// An useful macro used when reading gerber files; +#define IsNumber( x ) ( ( ( (x) >= '0' ) && ( (x) <='9' ) ) \ + || ( (x) == '-' ) || ( (x) == '+' ) || ( (x) == '.' ) ) + +class GERBVIEW_FRAME; +class D_CODE; + +/* gerber files have different parameters to define units and how items must be plotted. + * some are for the entire file, and other can change along a file. + * In Gerber world: + * an image is the entire gerber file and its "global" parameters + * a layer (that is very different from a board layer) is just a sub set of a file that + * have specific parameters + * if a Image parameter is set more than once, only the last value is used + * Some parameters can change along a file and are not layer specific: they are stored + * in GERBER_ITEM items, when instancied. + * + * In GerbView, to handle these parameters, there are 2 classes: + * GERBER_IMAGE : the main class containing most of parameters and data to plot a graphic layer + * Some of them can change along the file + * There is one GERBER_IMAGE per file and one graphic layer per file or GERBER_IMAGE + * GerbView does not read and merge 2 gerber file in one graphic layer: + * I believe this is not possible due to the constraints in Image parameters. + * GERBER_LAYER : containing the subset of parameters that is layer speficic + * A GERBER_IMAGE must include one GERBER_LAYER to define all parameters to plot a file. + * But a GERBER_IMAGE can use more than one GERBER_LAYER. + */ + +class GERBER_IMAGE; +class X2_ATTRIBUTE_FILEFUNCTION; + +class GERBER_LAYER +{ + friend class GERBER_IMAGE; +public: + + // These parameters are layer specfic: + wxString m_LayerName; // Layer name, from LN <name>* command + bool m_LayerNegative; // true = Negative Layer: command LP + wxRealPoint m_StepForRepeat; // X and Y offsets for Step and Repeat command + int m_XRepeatCount; // The repeat count on X axis + int m_YRepeatCount; // The repeat count on Y axis + bool m_StepForRepeatMetric; // false = Inches, true = metric + // needed here because repeated + // gerber items can have coordinates + // in different units than step parameters + // and the actual coordinates calculation must handle this + +public: + GERBER_LAYER(); + ~GERBER_LAYER(); +private: + void ResetDefaultValues(); +}; + +/** + * Class GERBER_IMAGE + * holds the Image data and parameters for one gerber file + * and layer parameters (TODO: move them in GERBER_LAYER class + */ +class GERBER_IMAGE +{ + GERBVIEW_FRAME* m_Parent; // the parent GERBVIEW_FRAME (used to display messages...) + D_CODE* m_Aperture_List[TOOLS_MAX_COUNT]; ///< Dcode (Aperture) List for this layer (max 999) + bool m_Exposure; ///< whether an aperture macro tool is flashed on or off + + GERBER_LAYER m_GBRLayerParams; // hold params for the current gerber layer + +public: + bool m_InUse; // true if this image is currently in use + // (a file is loaded in it) + wxString m_FileName; // Full File Name for this layer + wxString m_ImageName; // Image name, from IN <name>* command + bool m_IsX2_file; // true if a X2 gerber attribute was found in file + X2_ATTRIBUTE_FILEFUNCTION* m_FileFunction; // file function parameters, found in a %TF command + // or a G04 + wxString m_MD5_value; // MD5 value found in a %TF.MD5 command + wxString m_PartString; // string found in a %TF.Part command + int m_GraphicLayer; // Graphic layer Number + bool m_ImageNegative; // true = Negative image + bool m_ImageJustifyXCenter; // Image Justify Center on X axis (default = false) + bool m_ImageJustifyYCenter; // Image Justify Center on Y axis (default = false) + wxPoint m_ImageJustifyOffset; // Image Justify Offset on XY axis (default = 0,0) + bool m_GerbMetric; // false = Inches, true = metric + bool m_Relative; // false = absolute Coord, true = relative Coord + bool m_NoTrailingZeros; // true: remove tailing zeros. + bool m_DecimalFormat; // true: use floating point notations for coordinates + // If true, overrides m_NoTrailingZeros parameter. + wxPoint m_ImageOffset; // Coord Offset, from IO command + wxSize m_FmtScale; // Fmt 2.3: m_FmtScale = 3, fmt 3.4: m_FmtScale = 4 + wxSize m_FmtLen; // Nb chars per coord. ex fmt 2.3, m_FmtLen = 5 + int m_ImageRotation; // Image rotation (0, 90, 180, 270 only) in degrees + double m_LocalRotation; // Local rotation, in degrees, added to m_ImageRotation + // Note this value is stored in 0.1 degrees + wxPoint m_Offset; // Coord Offset, from OF command + wxRealPoint m_Scale; // scale (X and Y) of layer. + bool m_SwapAxis; // false (default) if A = X and B = Y + // true if A = Y, B = X + bool m_MirrorA; // true: miror / axe A (X) + bool m_MirrorB; // true: miror / axe B (Y) + int m_Iterpolation; // Linear, 90 arc, Circ. + int m_Current_Tool; // Current Tool (Dcode) number selected + int m_Last_Pen_Command; // Current or last pen state (0..9, set by Dn option with n <10 + int m_CommandState; // state of gerber analysis command. + wxPoint m_CurrentPos; // current specified coord for plot + wxPoint m_PreviousPos; // old current specified coord for plot + wxPoint m_IJPos; // IJ coord (for arcs & circles ) + + FILE* m_Current_File; // Current file to read + #define INCLUDE_FILES_CNT_MAX 10 + FILE* m_FilesList[INCLUDE_FILES_CNT_MAX + 2]; // Included files list + int m_FilesPtr; // Stack pointer for files list + + int m_Selected_Tool; // For hightlight: current selected Dcode + bool m_Has_DCode; // true = DCodes in file + // (false = no DCode -> separate DCode file + bool m_360Arc_enbl; // Enbl 360 deg circular interpolation + bool m_PolygonFillMode; // Enable polygon mode (read coord as a polygon descr) + int m_PolygonFillModeState; // In polygon mode: 0 = first segm, 1 = next segm + + APERTURE_MACRO_SET m_aperture_macros; ///< a collection of APERTURE_MACROS, sorted by name + +private: + int m_hasNegativeItems; // true if the image is negative or has some negative items + // Used to optimize drawing, because when there are no + // negative items screen refresh does not need + // to build an intermediate bitmap specfic to this image + // -1 = negative items are + // 0 = no negative items found + // 1 = have negative items found + +public: + GERBER_IMAGE( GERBVIEW_FRAME* aParent, int layer ); + virtual ~GERBER_IMAGE(); + void Clear_GERBER_IMAGE(); + int UsedDcodeNumber(); + virtual void ResetDefaultValues(); + + /** + * Function GetParent + * @return the GERBVIEW_FRAME parent of this GERBER_IMAGE + */ + GERBVIEW_FRAME* GetParent() const + { + return m_Parent; + } + + /** + * Function GetItemsList + * @return the first GERBER_DRAW_ITEM * item of the items list + */ + GERBER_DRAW_ITEM * GetItemsList(); + + /** + * Function GetLayerParams + * @return the current layers params + */ + GERBER_LAYER& GetLayerParams() + { + return m_GBRLayerParams; + } + + /** + * Function HasNegativeItems + * @return true if at least one item must be drawn in background color + * used to optimize screen refresh (when no items are in background color + * refresh can be faster) + */ + bool HasNegativeItems(); + + /** + * Function ReportMessage + * Add a message (a string) in message list + * for instance when reading a Gerber file + * @param aMessage = the straing to add in list + */ + void ReportMessage( const wxString aMessage ); + + /** + * Function ClearMessageList + * Clear the message list + * Call it before reading a Gerber file + */ + void ClearMessageList(); + + /** + * Function InitToolTable + */ + void InitToolTable(); + + /** + * Function ReadXYCoord + * Returns the current coordinate type pointed to by XnnYnn Text (XnnnnYmmmm) + */ + wxPoint ReadXYCoord( char*& Text ); + + /** + * Function ReadIJCoord + * Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm) + * These coordinates are relative, so if coordinate is absent, it's value + * defaults to 0 + */ + wxPoint ReadIJCoord( char*& Text ); + + // functions to read G commands or D commands: + int GCodeNumber( char*& Text ); + int DCodeNumber( char*& Text ); + + // functions to execute G commands or D commands: + bool Execute_G_Command( char*& text, int G_command ); + bool Execute_DCODE_Command( char*& text, int D_command ); + + /** + * Function ReadRS274XCommand + * reads a single RS274X command terminated with a % + */ + bool ReadRS274XCommand( char aBuff[GERBER_BUFZ], char* & text ); + + /** + * Function ExecuteRS274XCommand + * executes 1 command + */ + bool ExecuteRS274XCommand( int command, char aBuff[GERBER_BUFZ], + char* & text ); + + + /** + * Function ReadApertureMacro + * reads in an aperture macro and saves it in m_aperture_macros. + * @param aBuff a character buffer at least GERBER_BUFZ long that can be + * used to read successive lines from the gerber file. + * @param text A reference to a character pointer which gives the initial + * text to read from. + * @param gerber_file Which file to read from for continuation. + * @return bool - true if a macro was read in successfully, else false. + */ + bool ReadApertureMacro( char aBuff[GERBER_BUFZ], char* & text, + FILE * gerber_file ); + + + /** + * Function GetDCODE + * returns a pointer to the D_CODE within this GERBER for the given + * \a aDCODE. + * @param aDCODE The numeric value of the D_CODE to look up. + * @param createIfNoExist If true, then create the D_CODE if it does not + * exist. + * @return D_CODE* - the one implied by the given \a aDCODE, or NULL + * if the requested \a aDCODE is out of range. + */ + D_CODE* GetDCODE( int aDCODE, bool createIfNoExist = true ); + + /** + * Function FindApertureMacro + * looks up a previously read in aperture macro. + * @param aLookup A dummy APERTURE_MACRO with [only] the name field set. + * @return APERTURE_MACRO* - the one with a matching name, or NULL if + * not found. + */ + APERTURE_MACRO* FindApertureMacro( const APERTURE_MACRO& aLookup ); + + /** + * Function StepAndRepeatItem + * Gerber format has a command Step an Repeat + * This function must be called when reading a gerber file and + * after creating a new gerber item that must be repeated + * (i.e when m_XRepeatCount or m_YRepeatCount are > 1) + * @param aItem = the item to repeat + */ + void StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem ); + + /** + * Function DisplayImageInfo + * has knowledge about the frame and how and where to put status information + * about this object into the frame's message panel. + * Display info about Image Parameters. + */ + void DisplayImageInfo( void ); +}; + +/** + * @brief GERBER_IMAGE_LIST is a helper class to handle a list of GERBER_IMAGE files + * which are loaded and can be displayed + * there are 32 images max which can be loaded + */ +class GERBER_IMAGE_LIST +{ + // the list of loaded images (1 image = 1 gerber file) + std::vector<GERBER_IMAGE*> m_GERBER_List; + +public: + GERBER_IMAGE_LIST(); + ~GERBER_IMAGE_LIST(); + + //Accessor + GERBER_IMAGE* GetGbrImage( int aIdx ); + + /** + * Add a GERBER_IMAGE* at index aIdx + * or at the first free location if aIdx < 0 + * @param aGbrImage = the image to add + * @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) + * @return true if the index used, or -1 if no room to add image + */ + int AddGbrImage( GERBER_IMAGE* aGbrImage, int aIdx ); + + + /** + * remove all loaded data in list + */ + void ClearList(); + + /** + * remove the loaded data of image aIdx + * @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) + */ + void ClearImage( int aIdx ); + + /** + * @return a name for image aIdx which can be used in layers manager + * and layer selector + * is is "Layer n" (n = aIdx+1), followed by file attribute info (if X2 format) + * @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) + */ + const wxString GetDisplayName( int aIdx ); + + /** + * @return true if image is used (loaded and with items) + * @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) + */ + bool IsUsed( int aIdx ); + + /** + * Sort loaded images by Z order priority, if they have the X2 FileFormat info + * @param aDrawList: the draw list associated to the gerber images + * (SortImagesByZOrder updates the graphic layer of these items) + */ + void SortImagesByZOrder( GERBER_DRAW_ITEM* aDrawList ); +}; + + +extern GERBER_IMAGE_LIST g_GERBER_List; + +#endif // ifndef _CLASS_GERBER_H_ diff --git a/gerbview/class_X2_gerber_attributes.cpp b/gerbview/class_X2_gerber_attributes.cpp new file mode 100644 index 0000000..52d59b1 --- /dev/null +++ b/gerbview/class_X2_gerber_attributes.cpp @@ -0,0 +1,270 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_X2_gerber_attributes.cpp + */ + +/* + * Manage the gerber extensions (attributes) in the new X2 version + * only few extensions are handled + * See http://www.ucamco.com/files/downloads/file/81/the_gerber_file_format_specification.pdf + * + * gerber attributes in the new X2 version look like: + * %TF.FileFunction,Copper,L1,Top*% + * + * Currently: + * .FileFunction .FileFunction Identifies the file’s function in the PCB. + * Other Standard Attributes, not yet used in Gerbview: + * .Part Identifies the part the file represents, e.g. a single PCB + * .MD5 Sets the MD5 file signature or checksum. + */ + +#include <wx/log.h> +#include <class_X2_gerber_attributes.h> + +/* + * class X2_ATTRIBUTE + * The attribute value consists of a number of substrings separated by a “,” +*/ + +X2_ATTRIBUTE::X2_ATTRIBUTE() +{ +} + +X2_ATTRIBUTE::~X2_ATTRIBUTE() +{ +} + +/* return the attribute name (for instance .FileFunction) + * which is given by TF command. + */ +const wxString& X2_ATTRIBUTE::GetAttribute() +{ + return m_Prms.Item( 0 ); +} + +/* return a parameter + * aIdx = the index of the parameter + * aIdx = 0 is the parameter read after the TF function + * (the same as GetAttribute()) + */ +const wxString& X2_ATTRIBUTE::GetPrm( int aIdx) +{ + static const wxString dummy; + + if( GetPrmCount() < aIdx && aIdx >= 0 ) + return m_Prms.Item( aIdx ); + + return dummy; +} + +// Debug function: pring using wxLogMessage le list of parameters +void X2_ATTRIBUTE::DbgListPrms() +{ + wxLogMessage( wxT("prms count %d"), GetPrmCount() ); + + for( int ii = 0; ii < GetPrmCount(); ii++ ) + wxLogMessage( m_Prms.Item( ii ) ); +} + +/* + * parse a TF command and fill m_Prms by the parameters found. + * aFile = a FILE* ptr to the current Gerber file. + * buff = the buffer containing current Gerber data (GERBER_BUFZ size) + * text = a pointer to the first char to read in Gerber data + */ +bool X2_ATTRIBUTE::ParseAttribCmd( FILE* aFile, char *aBuffer, int aBuffSize, char* &aText ) +{ + bool ok = true; + wxString data; + + for( ; ; ) + { + while( *aText ) + { + switch( *aText ) + { + case '%': // end of command + return ok; // success completion + + case ' ': + case '\r': + case '\n': + aText++; + break; + + case '*': // End of block + m_Prms.Add( data ); + data.Empty(); + aText++; + break; + + case ',': // End of parameter + aText++; + m_Prms.Add( data ); + data.Empty(); + break; + + default: + data.Append( *aText ); + aText++; + break; + } + } + + // end of current line, read another one. + if( aBuffer ) + { + if( fgets( aBuffer, aBuffSize, aFile ) == NULL ) + { + // end of file + ok = false; + break; + } + + aText = aBuffer; + } + else + return ok; + } + + return ok; +} + +/* + * class X2_ATTRIBUTE_FILEFUNCTION ( from %TF.FileFunction in Gerber file) + * Example file function: + * %TF.FileFunction,Copper,L1,Top*% + * - Type. Such as copper, solder mask etc. + * - Position. Specifies where the file appears in the PCB layer structure. + * Corresponding position substring: + * Copper layer: L1, L2, L3...to indicate the layer position followed by Top, Inr or + * Bot. L1 is always the top copper layer. E.g. L2,Inr. + * Extra layer, e.g. solder mask: Top or Bot – defines the attachment of the layer. + * Drill/rout layer: E.g. 1,4 – where 1 is the start and 4 is the end copper layer. The + * pair 1,4 defines the span of the drill/rout file + * Optional index. This can be used in instances where for example there are two solder + * masks on the same side. The index counts from the PCB surface outwards. + */ +X2_ATTRIBUTE_FILEFUNCTION::X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBase ) + : X2_ATTRIBUTE() +{ + m_Prms = aAttributeBase.GetPrms(); + m_z_order = 0; + + //ensure at least 5 parameters + while( GetPrmCount() < 5 ) + m_Prms.Add( wxEmptyString ); + + set_Z_Order(); +} + +const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetFileType() +{ + // the type of layer (Copper , Soldermask ... ) + return m_Prms.Item( 1 ); +} + +const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerId() +{ + // the brd layer identifier: Ln (for Copper type) or Top, Bot + return m_Prms.Item( 2 ); +} + +const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetBrdLayerSide() +{ + if( IsCopper() ) + // the brd layer identifier: Top, Bot, Inr + return m_Prms.Item( 3 ); + else + // the brd layer identifier: Top, Bot ( same as GetBrdLayerId() ) + return m_Prms.Item( 2 ); +} + +const wxString& X2_ATTRIBUTE_FILEFUNCTION::GetLabel() +{ + if( IsCopper() ) + return m_Prms.Item( 4 ); + else + return m_Prms.Item( 3 ); +} + + +bool X2_ATTRIBUTE_FILEFUNCTION::IsCopper() +{ + // the filefunction label, if any + return GetFileType().IsSameAs( wxT( "Copper" ), false ); +} + +// Initialize the z order priority of the current file, from its attributes +// this priority is the order of layers from top to bottom to draw/display gerber images +// Stack up is( from external copper layer to external) +// copper, then solder paste, then solder mask, then silk screen. +// and global stackup is Front (top) layers then internal copper layers then Back (bottom) layers +void X2_ATTRIBUTE_FILEFUNCTION::set_Z_Order() +{ + m_z_order = -100; // low level + m_z_sub_order = 0; + + if( IsCopper() ) + { + // Copper layer: the priority is the layer Id + m_z_order = 0; + wxString num = GetBrdLayerId().Mid( 1 ); + long lnum; + if( num.ToLong( &lnum ) ) + m_z_sub_order = -lnum; + } + + if( GetFileType().IsSameAs( wxT( "Paste" ), false ) ) + { + // solder paste layer: the priority is top then bottom + m_z_order = 1; // for top + + if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) ) + m_z_order = -m_z_order; + } + + if( GetFileType().IsSameAs( wxT( "Soldermask" ), false ) ) + { + // solder mask layer: the priority is top then bottom + m_z_order = 2; // for top + + if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) ) + m_z_order = -m_z_order; + } + + if( GetFileType().IsSameAs( wxT( "Legend" ), false ) ) + { + // Silk screen layer: the priority is top then bottom + m_z_order = 3; // for top + + if( GetFileType().IsSameAs( wxT( "Legend" ), false ) ) + + if( GetBrdLayerId().IsSameAs( wxT( "Bot" ), false ) ) + m_z_order = -m_z_order; + } +} + diff --git a/gerbview/class_X2_gerber_attributes.h b/gerbview/class_X2_gerber_attributes.h new file mode 100644 index 0000000..cdd68b5 --- /dev/null +++ b/gerbview/class_X2_gerber_attributes.h @@ -0,0 +1,178 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_X2_gerber_attributes.h + */ + +#ifndef _CLASS_X2_GERBER_ATTRIBUTE_H_ +#define _CLASS_X2_GERBER_ATTRIBUTE_H_ + +/* + * Manage the gerber extensions (attributes) in the new X2 version + * only few extensions are handled + * See http://www.ucamco.com/files/downloads/file/81/the_gerber_file_format_specification.pdf + * + * gerber attributes in the new X2 version look like: + * %TF.FileFunction,Copper,L1,Top*% + * + * Currently: + * .FileFunction .FileFunction Identifies the file’s function in the PCB. + * Other Standard Attributes, not yet used in Gerbview: + * .Part Identifies the part the file represents, e.g. a single PCB + * .MD5 Sets the MD5 file signature or checksum. + */ + +#include <wx/arrstr.h> + +/** + * class X2_ATTRIBUTE + * The attribute value consists of a number of substrings separated by a “,” +*/ + +class X2_ATTRIBUTE +{ +protected: + wxArrayString m_Prms; ///< the list of parameters (after TF) in gbr file + ///< the first one is the attribute name, + ///< if starting by '.' + +public: + X2_ATTRIBUTE(); + ~X2_ATTRIBUTE(); + + /** + * @return the parameters list read in TF command. + */ + wxArrayString& GetPrms() { return m_Prms; } + + /** + * @return a parameter read in TF command. + * @param aIdx = the index of the parameter + * aIdx = 0 is the parameter read after the TF function + * (the same as GetAttribute()) + */ + const wxString& GetPrm( int aIdx ); + + /** + * @return the attribute name (for instance .FileFunction) + * which is given by TF command (i.e. the first parameter read). + */ + const wxString& GetAttribute(); + + /** + * @return the number of parameters read in TF command. + */ + int GetPrmCount() { return int( m_Prms.GetCount() ); } + + /** + * parse a TF command terminated with a % and fill m_Prms + * by the parameters found. + * @param aFile = a FILE* ptr to the current Gerber file. + * @param aBuffer = the buffer containing current Gerber data (can be null) + * @param aBuffSize = the size of the buffer + * @param aText = a pointer to the first char to read from Gerber data stored in aBuffer + * After parsing, text points the last char of the command line ('%') (X2 mode) + * or the end of line if the line does not contain '%' or aBuffer == NULL (X1 mode) + * @return true if no error. + */ + bool ParseAttribCmd( FILE* aFile, char *aBuffer, int aBuffSize, char* &aText ); + + /** + * Debug function: pring using wxLogMessage le list of parameters + */ + void DbgListPrms(); + + /** + * return true if the attribute is .FileFunction + */ + bool IsFileFunction() + { + return GetAttribute().IsSameAs( wxT(".FileFunction"), false ); + } + + /** + * return true if the attribute is .MD5 + */ + bool IsFileMD5() + { + return GetAttribute().IsSameAs( wxT(".MD5"), false ); + } + + /** + * return true if the attribute is .Part + */ + bool IsFilePart() + { + return GetAttribute().IsSameAs( wxT(".Part"), false ); + } +}; + +/** + * class X2_ATTRIBUTE_FILEFUNCTION ( from %TF.FileFunction in Gerber file) + * Example file function: + * %TF.FileFunction,Copper,L1,Top*% + * - Type. Such as copper, solder mask etc. + * - Position. Specifies where the file appears in the PCB layer structure. + * Corresponding position substring: + * Copper layer: L1, L2, L3...to indicate the layer position followed by Top, Inr or + * Bot. L1 is always the top copper layer. E.g. L2,Inr. + * Extra layer, e.g. solder mask: Top or Bot – defines the attachment of the layer. + * Drill/rout layer: E.g. 1,4 – where 1 is the start and 4 is the end copper layer. The + * pair 1,4 defines the span of the drill/rout file + * Optional index. This can be used in instances where for example there are two solder + * masks on the same side. The index counts from the PCB surface outwards. + */ + +class X2_ATTRIBUTE_FILEFUNCTION : public X2_ATTRIBUTE +{ + int m_z_order; // the z order of the layer for a board + int m_z_sub_order; // the z sub_order of the copper layer for a board + +public: + X2_ATTRIBUTE_FILEFUNCTION( X2_ATTRIBUTE& aAttributeBase ); + + bool IsCopper(); ///< return true if the filefunction type is "Copper" + + const wxString& GetFileType(); ///< the type of layer (Copper, Soldermask ... ) + const wxString& GetBrdLayerId(); ///< the brd layer identifier: Ln, only for Copper type + ///< or Top, Bot for other types + const wxString& GetBrdLayerSide(); ///< the brd layer Pos: Top, Bot, Inr + ///< same as GetBrdLayerId() for non copper type + const wxString& GetLabel(); ///< the filefunction label, if any + + int GetZOrder() { return m_z_order; } ///< the Order of the board layer, + ///< from front (Top) side to back (Bot) side + int GetZSubOrder() { return m_z_sub_order; } ///< the Order of the bdr copper layer, + ///< from front (Top) side to back (Bot) side + +private: + + /** + * Initialize the z order priority of the current file, from its attributes + */ + void set_Z_Order(); +}; + +#endif // _CLASS_X2_GERBER_ATTRIBUTE_H_ diff --git a/gerbview/class_am_param.cpp b/gerbview/class_am_param.cpp new file mode 100644 index 0000000..63306a4 --- /dev/null +++ b/gerbview/class_am_param.cpp @@ -0,0 +1,251 @@ +/** + * @file class_am_param.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <class_am_param.h> +#include <class_aperture_macro.h> + +extern int ReadInt( char*& text, bool aSkipSeparator = true ); +extern double ReadDouble( char*& text, bool aSkipSeparator = true ); + +/* Class AM_PARAM + * holds a parameter value for an "aperture macro" as defined within + * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, + * or depend on some defered values, defined in a D_CODE, by the ADD command. + * Note the actual value could need an evaluation from an arithmetical expression + * items in the expression are stored in . + * A simple definition is just a value stored in one item in m_paramStack + */ +AM_PARAM::AM_PARAM( ) +{ + m_index = -1; +} + +/** + * Function IsImmediate + * tests if this AM_PARAM holds an immediate parameter or has parameter + * held by an owning D_CODE. + */ +bool AM_PARAM::IsImmediate() const +{ + bool isimmediate = true; + for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) + { + if( m_paramStack[ii].IsDefered() ) + { // a defered value is found in operand list, + // so the parameter is not immediate + isimmediate = false; + break; + } + } + return isimmediate; +} + +double AM_PARAM::GetValue( const D_CODE* aDcode ) const +{ + double paramvalue = 0.0; + double curr_value = 0.0; + parm_item_type state = POPVALUE; + + for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) + { + AM_PARAM_ITEM item = m_paramStack[ii]; + switch( item.GetType() ) + { + case ADD: + case SUB: + case MUL: + case DIV: // just an operator for next parameter value: store it + state = item.GetType(); + break; + + case PUSHPARM: + // get the parameter from the aDcode + if( aDcode ) // should be always true here + { + if( item.GetIndex() <= aDcode->GetParamCount() ) + curr_value = aDcode->GetParam( item.GetIndex() ); + else // Get parameter from local param definition + { + const APERTURE_MACRO * am_parent = aDcode->GetMacro(); + curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() ); + } + } + else + { + wxLogDebug( wxT( "AM_PARAM::GetValue(): NULL param aDcode\n" ) ); + } + // Fall through + case PUSHVALUE: // a value is on the stack: + if( item.GetType() == PUSHVALUE ) + curr_value = item.GetValue(); + switch( state ) + { + case POPVALUE: + paramvalue = curr_value; + break; + + case ADD: + paramvalue += curr_value; + break; + + case SUB: + paramvalue -= curr_value; + break; + + case MUL: + paramvalue *= curr_value; + break; + + case DIV: + paramvalue /= curr_value; + break; + + default: + wxLogDebug( wxT( "AM_PARAM::GetValue() : unexpected operator\n" ) ); + break; + } + break; + + default: + wxLogDebug( wxT( "AM_PARAM::GetValue(): unexpected type\n" ) ); + break; + } + } + return paramvalue; +} + +/** + * add an operator/operand to the current stack + * aType = NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE + * aValue required only for PUSHVALUE (double) or PUSHPARM (int) aType. + */ +void AM_PARAM::PushOperator( parm_item_type aType, double aValue ) +{ + AM_PARAM_ITEM item( aType, aValue); + m_paramStack.push_back( item ); +} + +void AM_PARAM::PushOperator( parm_item_type aType, int aValue ) +{ + AM_PARAM_ITEM item( aType, aValue); + m_paramStack.push_back( item ); +} + +/** + * Function ReadParam + * Read one aperture macro parameter + * a parameter can be: + * a number + * a reference to an aperture definition parameter value: $1 ot $3 ... + * a parameter definition can be complex and have operators between numbers and/or other parameter + * like $1+3 or $2x2.. + * Note minus sign is not always an operator. It can be the sign of a value. + * Parameters are separated by a comma ( of finish by *) + * @param aText = pointer to the parameter to read. Will be modified to point to the next field + * @return true if a param is read, or false + */ +bool AM_PARAM::ReadParam( char*& aText ) +{ + bool found = false; + int ivalue; + double dvalue; + bool end = false; + + while( !end ) + { + switch( *aText ) + { + case ',': + aText++; + // fall through + case 0: // EOL + case '*': // Terminator in a gerber command + end = true; + break; + + case ' ': + aText++; + break; + + case '$': + // defered value defined later, in ADD command which define defered parameters + ++aText; + ivalue = ReadInt( aText, false ); + if( m_index < 1 ) + SetIndex( ivalue ); + PushOperator( PUSHPARM, ivalue ); + found = true; + break; + + case '/': + PushOperator( DIV ); + aText++; + break; + + case 'x': + case 'X': + PushOperator( MUL ); + aText++; + break; + + case '-': + case '+': + // Test if this is an operator between 2 params, or the sign of a value + if( m_paramStack.size() > 0 && !m_paramStack.back().IsOperator() ) + { // Seems an operator + PushOperator( *aText == '+' ? ADD : SUB ); + aText++; + } + else + { // seems the sign of a value + dvalue = ReadDouble( aText, false ); + PushOperator( PUSHVALUE, dvalue ); + found = true; + } + break; + + case '=': // A local definition found like $4=$3/2 + // At this point, one defered parameter is expected to be read. + // this parameter value (the index) is stored in m_index. + // The list of items is cleared + aText++; + m_paramStack.clear(); + found = false; + break; + + default: + dvalue = ReadDouble( aText, false ); + PushOperator( PUSHVALUE, dvalue ); + found = true; + break; + } + } + + return found; +} diff --git a/gerbview/class_am_param.h b/gerbview/class_am_param.h new file mode 100644 index 0000000..c60e311 --- /dev/null +++ b/gerbview/class_am_param.h @@ -0,0 +1,268 @@ +/** + * @file class_am_param.h + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2015 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _AM_PARAM_H_ +#define _AM_PARAM_H_ + +/* + * An aperture macro defines a complex shape and is a list of aperture primitives. + * Each aperture primitive defines a simple shape (circle, rect, regular polygon...) + * Inside a given aperture primitive, a fixed list of parameters defines info + * about the shape: size, thickness, number of vertex ... + * + * Each parameter can be an immediate value or a defered value. + * When value is defered, it is defined when the aperture macro is instancied by + * an ADD macro command + * + * Actual values of a parameter can also be the result of an arithmetic operation. + * + * Here is some examples: + * An immediate value: + * 3.5 + * A deferend value: + * $2 means: replace me by the second value given in the ADD command + * Actual value as arithmetic calculation: + * $2/2+1 + * + * Note also a defered parameter can be defined in aperture macro, + * but outside aperture primitives. Example + * %AMRECTHERM* + * $4=$3/2* parameter $4 is half value of parameter $3 + * 21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0* + * For the aperture primitive, parameters $1 to $3 will be defined in ADD command, + * and $4 is defined inside the macro + * + * Some examples of aperture macro definition + * A simple definition, no parameters: + * %AMMOIRE10* + * 6,0,0,0.350000,0.005,0.050,3,0.005,0.400000,0.0*% + * Example of instanciation: + * %ADD19THERM19*% + * + * A simple definition, one parameter: + * %AMCIRCLE* + * 1,1,$1,0,0* + * Example of instanciation: + * %ADD11CIRCLE,.5*% + * + * A definition, with parameters and arithmetic operations: + * %AMVECTOR* + * 2,1,$1,0,0,$2+1,$3,-135*% + * Example of instanciation: + * %ADD12VECTOR,0.05X0X0*% + * + * A more complicated aperture macro definition, with parameters and arihmetic operations: + * %AMRNDREC* + * 0 this is a comment* + * 21,1,$1+$1,$2+$2-$3-$3,0,0,0* + * 21,1,$1+$1-$3-$3,$2+$2,0,0,0* + * 1,1,$3+$3,$1-$3,$2-$3* + * 1,1,$3+$3,$3-$1,$2-$3* + * 1,1,$3+$3,$1-$3,$3-$2* + * 1,1,$3+$3,$3-$1,$3-$2*% + * Example of instanciation: + * + * A more complicated sample of aperture macro definition: + * G04 Rectangular Thermal Macro, params: W/2, H/2, T/2 * + * %AMRECTHERM* + * $4=$3/2* + * 21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0* + * 21,1,$1-$3,$2-$3,0-$1/2-$4,$2/2+$4,0* + * 21,1,$1-$3,$2-$3,$1/2+$4,0-$2/2-$4,0* + * 21,1,$1-$3,$2-$3,$1/2+$4,$2/2+$4,0*% + * Example of instanciation: + * %ADD28RECTHERM,0.035591X0.041496X0.005000*% + */ + +#include <vector> + +#include <dcode.h> +/* +Values of a parameter can be the result of an arithmetic operation, +between immediate values and defered value. +From an idea found in Gerbv, here is the way to evaluate a parameter. +a AM_PARAM_ITEM holds info about operands and operators in a parameter definition +( a AM_PARAM ) like $2+$2-$3-$3/2 + +There is no precedence defined in gerber RS274X, so actual value is calculated step to step. +Parameter definition is described by a very primitive assembler. +This "program "should describe how to calculate the parameter. +The assembler consist of 8 instruction intended for a stackbased machine. +The instructions are: +NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE + +The instructions +---------------- +NOP : The no operation. This is the default instruction and are + added as a security measure. +PUSHVALUE : Pushes an arithmetical value on the stack. This machine only works with floats + on the stack. +PUSHPARM: Pushes a defered parameter onto the stack. Gerber aperture macros accepts + parameters to be set when later declared, so the same macro can + be used at several instances. Which parameter to be set is an integer + and starts with 1. definition is like $1 or $3 +ADD : The mathematical operation +. Takes the two uppermost values on the + the stack, adds them and pushes the result back onto the stack. +SUB : Same as ADD, but with -. +MUL : Same as ADD, but with *. +DIV : Same as ADD, but with /. +POPVALUE : used when evaluate the expression: store current calculated value +*/ + +enum parm_item_type +{ + NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, POPVALUE +}; + +/** + * Class AM_PARAM + * holds an operand for an AM_PARAM as defined within + * standard RS274X. The \a value field can be a constant, i.e. "immediate" + * parameter or it may not be used if this param is going to defer to the + * referencing aperture macro. In that case, the \a index field is an index + * into the aperture macro's parameters. + */ +class AM_PARAM_ITEM +{ +private: + parm_item_type m_type; // the type of item + double m_dvalue; // the value, for PUSHVALUE type item + int m_ivalue; // the integer value, for PUSHPARM type item + +public: + AM_PARAM_ITEM( parm_item_type aType, double aValue ) + { + m_type = aType; + m_dvalue = aValue; + m_ivalue = 0; + } + AM_PARAM_ITEM( parm_item_type aType, int aValue ) + { + m_type = aType; + m_dvalue = 0.0; + m_ivalue = aValue; + } + + void SetValue( double aValue ) + { + m_dvalue = aValue; + } + double GetValue( ) const + { + return m_dvalue; + } + parm_item_type GetType() const + { + return m_type; + } + unsigned GetIndex() const + { + return (unsigned) m_ivalue; + } + bool IsOperator() const + { + return m_type == ADD || m_type == SUB || m_type == MUL || m_type == DIV; + } + bool IsOperand() const + { + return m_type == PUSHVALUE || m_type == PUSHPARM; + } + bool IsDefered() const + { + return m_type == PUSHPARM; + } +}; + +/** + * Class AM_PARAM + * holds a parameter value for an "aperture macro" as defined within + * standard RS274X. The parameter can be a constant, i.e. "immediate" parameter, + * or depend on some defered values, defined in a D_CODE, by the ADD command. + * Note the actual value could need an evaluation from an arithmetical expression + * items in the expression are stored in . + * A simple definition is just a value stored in one item in m_paramStack + */ +class AM_PARAM +{ +private: + int m_index; // has meaning to define parameter local to an aperture macro + std::vector<AM_PARAM_ITEM> m_paramStack; // list of operands/operators to evalutate the actual value + // if a par def is $3/2, there are 3 items in stack: + // 3 (type PUSHPARM) , / (type DIV), 2 (type PUSHVALUE) + +public: + AM_PARAM(); + + /** + * function PushOperator + * add an operator/operand to the current stack + * @param aType = the type of item (NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE) + * @param aValue = the item value, double for PUSHVALUE or int for PUSHPARM type. + */ + void PushOperator( parm_item_type aType, double aValue ); + void PushOperator( parm_item_type aType, int aValue = 0); + + double GetValue( const D_CODE* aDcode ) const; + + /** + * Function IsImmediate + * tests if this AM_PARAM holds an immediate parameter or is a pointer + * into a parameter held by an owning D_CODE. + * @return true if the value is immediate, i.e. no defered value in operands used in its definition + */ + bool IsImmediate() const; + + unsigned GetIndex() const + { + return (unsigned) m_index; + } + + void SetIndex( int aIndex ) + { + m_index = aIndex; + } + + /** + * Function ReadParam + * Read one aperture macro parameter + * a parameter can be: + * a number + * a reference to an aperture definition parameter value: $1 ot $3 ... + * a parameter definition can be complex and have operators between numbers and/or other parameter + * like $1+3 or $2x2.. + * Parameters are separated by a comma ( of finish by *) + * @param aText = pointer to the parameter to read. Will be modified to point to the next field + * @return true if a param is read, or false + */ + bool ReadParam( char*& aText ); +}; + +typedef std::vector<AM_PARAM> AM_PARAMS; + +#endif // _AM_PARAM_H_ diff --git a/gerbview/class_aperture_macro.cpp b/gerbview/class_aperture_macro.cpp new file mode 100644 index 0000000..0c48a5b --- /dev/null +++ b/gerbview/class_aperture_macro.cpp @@ -0,0 +1,811 @@ +/** + * @file class_aperture_macro.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> +#include <macros.h> +#include <trigo.h> +#include <gr_basic.h> + +#include <gerbview.h> +#include <class_GERBER.h> + + + +/** + * Function scaletoIU + * converts a distance given in floating point to our internal units + */ +extern int scaletoIU( double aCoord, bool isMetric ); // defined it rs274d_read_XY_and_IJ_coordiantes.cpp + +/** + * Function mapPt + * translates a point from the aperture macro coordinate system to our + * deci-mils coordinate system. + * @return wxPoint - The GerbView coordinate system vector. + */ +static wxPoint mapPt( double x, double y, bool isMetric ) +{ + wxPoint ret( scaletoIU( x, isMetric ), scaletoIU( y, isMetric ) ); + + return ret; +} + +/** + * Function mapExposure + * translates the first parameter from an aperture macro into a current + * exposure setting. + * @param aParent = a GERBER_DRAW_ITEM that handle: + * ** m_Exposure A dynamic setting which can change throughout the + * reading of the gerber file, and it indicates whether the current tool + * is lit or not. + * ** m_ImageNegative A dynamic setting which can change throughout the reading + * of the gerber file, and it indicates whether the current D codes are to + * be interpreted as erasures or not. + * @return true to draw with current color, false to draw with alt color (erase) + */ +bool AM_PRIMITIVE::mapExposure( GERBER_DRAW_ITEM* aParent ) +{ + bool exposure; + switch( primitive_id ) + { + case AMP_CIRCLE: + case AMP_LINE2: + case AMP_LINE20: + case AMP_LINE_CENTER: + case AMP_LINE_LOWER_LEFT: + case AMP_OUTLINE: + case AMP_THERMAL: + case AMP_POLYGON: + // All have an exposure parameter and can return true or false + switch( GetExposure(aParent) ) + { + case 0: // exposure always OFF + exposure = false; + break; + + default: + case 1: // exposure always OON + exposure = true; + break; + + case 2: // reverse exposure + exposure = !aParent->GetLayerPolarity(); + } + break; + + case AMP_MOIRE: + case AMP_EOF: + case AMP_UNKNOWN: + default: + return true; // All have no exposure parameter and must return true (no change for exposure) + break; + } + + return exposure ^ aParent->m_imageParams->m_ImageNegative; +} + + +/** + * Function GetExposure + * returns the first parameter in integer form. Some but not all primitives + * use the first parameter as an exposure control. + */ +int AM_PRIMITIVE::GetExposure(GERBER_DRAW_ITEM* aParent) const +{ + // No D_CODE* for GetValue() + wxASSERT( params.size() && params[0].IsImmediate() ); + return (int) params[0].GetValue( aParent->GetDcodeDescr() ); +} + +/** + * Function DrawBasicShape + * Draw the primitive shape for flashed items. + */ +void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, + wxDC* aDC, + EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, + wxPoint aShapePos, + bool aFilledShape ) +{ + static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation + polybuffer.clear(); + + wxPoint curPos = aShapePos; + D_CODE* tool = aParent->GetDcodeDescr(); + double rotation; + if( mapExposure( aParent ) == false ) + { + std::swap( aColor, aAltColor ); + } + + switch( primitive_id ) + { + case AMP_CIRCLE: // Circle, given diameter and position + { + /* Generated by an aperture macro declaration like: + * "1,1,0.3,0.5, 1.0*" + * type (1), exposure, diameter, pos.x, pos.y + * type is not stored in parameters list, so the first parameter is exposure + */ + curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); + curPos = aParent->GetABPosition( curPos ); + int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2; + if( !aFilledShape ) + GRCircle( aClipBox, aDC, curPos, radius, 0, aColor ); + else + GRFilledCircle( aClipBox, aDC, curPos, radius, aColor ); + } + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + { + /* Generated by an aperture macro declaration like: + * "2,1,0.3,0,0, 0.5, 1.0,-135*" + * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = params[6].GetValue( tool ) * 10.0; + if( rotation != 0) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_LINE_CENTER: + { + /* Generated by an aperture macro declaration like: + * "21,1,0.3,0.03,0,0,-135*" + * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = params[5].GetValue( tool ) * 10.0; + if( rotation != 0 ) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + /* Generated by an aperture macro declaration like: + * "22,1,0.3,0.03,0,0,-135*" + * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = params[5].GetValue( tool ) * 10.0; + if( rotation != 0) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_THERMAL: + { + /* Generated by an aperture macro declaration like: + * "7, 0,0,1.0,0.3,0.01,-13*" + * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation + * type is not stored in parameters list, so the first parameter is center.x + */ + curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = params[5].GetValue( tool ) * 10.0; + + // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer. + // We must draw 4 sub-shapes rotated by 90 deg + std::vector<wxPoint> subshape_poly; + for( int ii = 0; ii < 4; ii++ ) + { + subshape_poly = polybuffer; + double sub_rotation = rotation + 900 * ii; + for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) + RotatePoint( &subshape_poly[jj], -sub_rotation ); + + // Move to current position: + for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) + { + subshape_poly[jj] += curPos; + subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] ); + } + + GRClosedPoly( aClipBox, aDC, + subshape_poly.size(), &subshape_poly[0], true, aAltColor, + aAltColor ); + } + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles + { + curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), + m_GerbMetric ); + + /* Generated by an aperture macro declaration like: + * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" + * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation + * type is not stored in parameters list, so the first parameter is pos.x + */ + int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ); + int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ); + int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ); + int numCircles = KiROUND( params[5].GetValue( tool ) ); + + // Draw circles: + wxPoint center = aParent->GetABPosition( curPos ); + // adjust outerDiam by this on each nested circle + int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ? + for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) + { + if( outerDiam <= 0 ) + break; + if( !aFilledShape ) + { + // draw the border of the pen's path using two circles, each as narrow as possible + GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor ); + GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor ); + } + else // Filled mode + { + GRCircle( aClipBox, aDC, center, + (outerDiam - penThickness) / 2, penThickness, aColor ); + } + } + + // Draw the cross: + ConvertShapeToPolygon( aParent, polybuffer ); + + rotation = params[8].GetValue( tool ) * 10.0; + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + // shape rotation: + RotatePoint( &polybuffer[ii], -rotation ); + // Move to current position: + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_OUTLINE: + { + /* Generated by an aperture macro declaration like: + * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" + * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + int numPoints = (int) params[1].GetValue( tool ); + rotation = params[numPoints * 2 + 4].GetValue( tool ) * 10.0; + wxPoint pos; + // Read points. numPoints does not include the starting point, so add 1. + for( int i = 0; i<numPoints + 1; ++i ) + { + int jj = i * 2 + 2; + pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric ); + pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric ); + polybuffer.push_back(pos); + } + // rotate polygon and move it to the actual position + // shape rotation: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_POLYGON: // Is a regular polygon + /* Generated by an aperture macro declaration like: + * "5,1,0.6,0,0,0.5,25" + * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); + // Creates the shape: + ConvertShapeToPolygon( aParent, polybuffer ); + + // rotate polygon and move it to the actual position + rotation = params[5].GetValue( tool ) * 10.0; + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + RotatePoint( &polybuffer[ii], -rotation ); + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + break; + + case AMP_EOF: + // not yet supported, waiting for you. + break; + + case AMP_UNKNOWN: + default: + DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); + break; + } +} + + +/** + * Function ConvertShapeToPolygon (virtual) + * convert a shape to an equivalent polygon. + * Arcs and circles are approximated by segments + * Useful when a shape is not a graphic primitive (shape with hole, + * rotated shape ... ) and cannot be easily drawn. + * note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted + * because circles are very easy to draw (no rotation problem) so convert them in polygons, + * and draw them as polygons is not a good idea. + */ +void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, + std::vector<wxPoint>& aBuffer ) +{ + D_CODE* tool = aParent->GetDcodeDescr(); + + switch( primitive_id ) + { + case AMP_CIRCLE: // Circle, currently convertion not needed + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + { + int width = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); + wxPoint start = mapPt( params[2].GetValue( tool ), + params[3].GetValue( tool ), m_GerbMetric ); + wxPoint end = mapPt( params[4].GetValue( tool ), + params[5].GetValue( tool ), m_GerbMetric ); + wxPoint delta = end - start; + int len = KiROUND( EuclideanNorm( delta ) ); + + // To build the polygon, we must create a horizonta polygon starting to "start" + // and rotate it to have it end point to "end" + wxPoint currpt; + currpt.y += width / 2; // Upper left + aBuffer.push_back( currpt ); + currpt.x = len; // Upper right + aBuffer.push_back( currpt ); + currpt.y -= width; // lower right + aBuffer.push_back( currpt ); + currpt.x = 0; // Upper left + aBuffer.push_back( currpt ); + + // Rotate rectangle and move it to the actual start point + double angle = ArcTangente( delta.y, delta.x ); + + for( unsigned ii = 0; ii < 4; ii++ ) + { + RotatePoint( &aBuffer[ii], -angle ); + aBuffer[ii] += start; + } + } + break; + + case AMP_LINE_CENTER: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric ); + + // Build poly: + pos.x -= size.x / 2; + pos.y -= size.y / 2; // Lower left + aBuffer.push_back( pos ); + pos.y += size.y; // Upper left + aBuffer.push_back( pos ); + pos.x += size.x; // Upper right + aBuffer.push_back( pos ); + pos.y -= size.y; // lower right + aBuffer.push_back( pos ); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( + tool ), m_GerbMetric ); + + // Build poly: + aBuffer.push_back( lowerLeft ); + lowerLeft.y += size.y; // Upper left + aBuffer.push_back( lowerLeft ); + lowerLeft.x += size.x; // Upper right + aBuffer.push_back( lowerLeft ); + lowerLeft.y -= size.y; // lower right + aBuffer.push_back( lowerLeft ); + } + break; + + case AMP_THERMAL: + { + // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first + // rotated by 90, 180 and 270 deg. + // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness + int outerRadius = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; + int innerRadius = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ) / 2; + int halfthickness = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; + double angle_start = RAD2DECIDEG( asin( (double) halfthickness / innerRadius ) ); + + // Draw shape in the first cadrant (X and Y > 0) + wxPoint pos, startpos; + + // Inner arc + startpos.x = innerRadius; + double angle_end = 900 - angle_start; + for( double angle = angle_start; angle < angle_end; angle += 100 ) + { + pos = startpos; + RotatePoint( &pos, angle ); + aBuffer.push_back( pos ); + } + + // Last point + pos = startpos; + RotatePoint( &pos, angle_end ); + aBuffer.push_back( pos ); + + // outer arc + startpos.x = outerRadius; + startpos.y = 0; + angle_start = RAD2DECIDEG( asin( (double) halfthickness / outerRadius ) ); + angle_end = 900 - angle_start; + + // First point, near Y axis, outer arc + for( double angle = angle_end; angle > angle_start; angle -= 100 ) + { + pos = startpos; + RotatePoint( &pos, angle ); + aBuffer.push_back( pos ); + } + + // last point + pos = startpos; + RotatePoint( &pos, angle_start ); + aBuffer.push_back( pos ); + + aBuffer.push_back( aBuffer[0] ); // Close poly + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon + // because circles can be drawn easily + { + int crossHairThickness = scaletoIU( params[6].GetValue( tool ), m_GerbMetric ); + int crossHairLength = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); + + // Create cross. First create 1/4 of the shape. + // Others point are the same, totated by 90, 180 and 270 deg + wxPoint pos( crossHairThickness / 2, crossHairLength / 2 ); + aBuffer.push_back( pos ); + pos.y = crossHairThickness / 2; + aBuffer.push_back( pos ); + pos.x = -crossHairLength / 2; + aBuffer.push_back( pos ); + pos.y = -crossHairThickness / 2; + aBuffer.push_back( pos ); + + // Copy the 4 shape, rotated by 90, 180 and 270 deg + for( int jj = 1; jj <= 3; jj ++ ) + { + for( int ii = 0; ii < 4; ii++ ) + { + pos = aBuffer[ii]; + RotatePoint( &pos, jj*900 ); + aBuffer.push_back( pos ); + } + } + } + break; + + case AMP_OUTLINE: + // already is a polygon. Do nothing + break; + + case AMP_POLYGON: // Creates a regular polygon + { + int vertexcount = KiROUND( params[1].GetValue( tool ) ); + int radius = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; + // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis + if( vertexcount < 3 ) + vertexcount = 3; + if( vertexcount > 10 ) + vertexcount = 10; + for( int ii = 0; ii <= vertexcount; ii++ ) + { + wxPoint pos( radius, 0); + RotatePoint( &pos, ii * 3600 / vertexcount ); + aBuffer.push_back( pos ); + } + } + break; + + case AMP_COMMENT: + case AMP_UNKNOWN: + case AMP_EOF: + break; + } +} + +/** GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of the shape of some primitives + * one cannot calculate the "size" of a shape (only abounding box) + * but here, the "dimension" of the shape is the diameter of the primitive + * or for lines the width of the line + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return a dimension, or -1 if no dim to calculate + */ +int AM_PRIMITIVE::GetShapeDim( GERBER_DRAW_ITEM* aParent ) +{ + int dim = -1; + D_CODE* tool = aParent->GetDcodeDescr(); + + switch( primitive_id ) + { + case AMP_CIRCLE: + // params = exposure, diameter, pos.x, pos.y + dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // Diameter + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + dim = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ); // linne width + break; + + case AMP_LINE_CENTER: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + dim = std::min(size.x, size.y); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + dim = std::min(size.x, size.y); + } + break; + + case AMP_THERMAL: + { + // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first + // rotated by 90, 180 and 270 deg. + // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness + dim = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles. + dim = scaletoIU( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len + break; + + case AMP_OUTLINE: // a free polygon : + // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?) + { + // exposure, corners count, corner1.x, corner.1y, ..., rotation + int numPoints = (int) params[1].GetValue( tool ); + // Read points. numPoints does not include the starting point, so add 1. + // and calculate the bounding box; + wxSize pos_min, pos_max, pos; + for( int i = 0; i<numPoints + 1; ++i ) + { + int jj = i * 2 + 2; + pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric ); + pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric ); + if( i == 0 ) + pos_min = pos_max = pos; + else + { + // upper right corner: + if( pos_min.x > pos.x ) + pos_min.x = pos.x; + if( pos_min.y > pos.y ) + pos_min.y = pos.y; + // lower left corner: + if( pos_max.x < pos.x ) + pos_max.x = pos.x; + if( pos_max.y < pos.y ) + pos_max.y = pos.y; + } + } + // calculate dim + wxSize size; + size.x = pos_max.x - pos_min.x; + size.y = pos_max.y - pos_min.y; + dim = std::min( size.x, size.y ); + } + break; + + case AMP_POLYGON: // Regular polygon + dim = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius + break; + + case AMP_COMMENT: + case AMP_UNKNOWN: + case AMP_EOF: + break; + } + return dim; +} + + +/** + * Function DrawApertureMacroShape + * Draw the primitive shape for flashed items. + * When an item is flashed, this is the shape of the item + */ +void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, wxDC* aDC, + EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, + wxPoint aShapePos, bool aFilledShape ) +{ + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + prim_macro->DrawBasicShape( aParent, aClipBox, aDC, + aColor, aAltColor, + aShapePos, + aFilledShape ); + } +} + +/* Function HasNegativeItems + * return true if this macro has at least one aperture primitives + * that must be drawn in background color + * used to optimize screen refresh + */ +bool APERTURE_MACRO::HasNegativeItems( GERBER_DRAW_ITEM* aParent ) +{ + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + if( prim_macro->mapExposure( aParent ) == false ) // = is negative + return true; + } + + return false; +} + + +/** GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of a shape using many primitives + * one cannot calculate the "size" of a shape (only abounding box) + * but most of aperture macro are using one or few primitives + * and the "dimension" of the shape is the diameter of the primitive + * (or the max diameter of primitives) + * @return a dimension, or -1 if no dim to calculate + */ +int APERTURE_MACRO::GetShapeDim( GERBER_DRAW_ITEM* aParent ) +{ + int dim = -1; + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + int pdim = prim_macro->GetShapeDim( aParent ); + if( dim < pdim ) + dim = pdim; + } + + return dim; +} + + +/** + * function GetLocalParam + * Usually, parameters are defined inside the aperture primitive + * using immediate mode or defered mode. + * in defered mode the value is defined in a DCODE that want to use the aperture macro. + * But some parameters are defined outside the aperture primitive + * and are local to the aperture macro + * @return the value of a defered parameter defined inside the aperture macro + * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate + */ +double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const +{ + // find parameter descr. + const AM_PARAM * param = NULL; + for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ ) + { + if( m_localparamStack[ii].GetIndex() == aParamId ) + { + param = &m_localparamStack[ii]; + break; + } + } + if ( param == NULL ) // not found + return 0.0; + // Evaluate parameter + double value = param->GetValue( aDcode ); + return value; +} diff --git a/gerbview/class_aperture_macro.h b/gerbview/class_aperture_macro.h new file mode 100644 index 0000000..959a254 --- /dev/null +++ b/gerbview/class_aperture_macro.h @@ -0,0 +1,262 @@ +/** + * @file class_aperture_macro.h + */ + +#ifndef _APERTURE_MACRO_H_ +#define _APERTURE_MACRO_H_ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <vector> +#include <set> + +#include <base_struct.h> +#include <class_am_param.h> + +/* + * An aperture macro defines a complex shape and is a list of aperture primitives. + * Each aperture primitive defines a simple shape (circle, rect, regular polygon...) + * Inside a given aperture primitive, a fixed list of parameters defines info + * about the shape: size, thickness, number of vertex ... + * + * Each parameter can be an immediate value or a defered value. + * When value is defered, it is defined when the aperture macro is instancied by + * an ADD macro command + * Note also a defered parameter can be defined in aperture macro, + * but outside aperture primitives. Example + * %AMRECTHERM* + * $4=$3/2* parameter $4 is half value of parameter $3 + * 21,1,$1-$3,$2-$3,0-$1/2-$4,0-$2/2-$4,0* + * For the aperture primitive, parameters $1 to $3 will be defined in ADD command, + * and $4 is defined inside the macro + */ + +/** + * Enum AM_PRIMITIVE_ID + * is the set of all "aperture macro primitives" (primitive numbers). See + * Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf + * aperture macro primitives are basic shapes which can be combined to create a complex shape + * This complex shape is flashed. + */ +enum AM_PRIMITIVE_ID { + AMP_UNKNOWN = -1, // A value for uninitialized AM_PRIMITIVE. + AMP_COMMENT = 0, // A primitive description is not really a primitive, this is a comment + AMP_CIRCLE = 1, // Circle. (diameter and position) + AMP_LINE2 = 2, // Line with rectangle ends. (Width, start and end pos + rotation) + AMP_LINE20 = 20, // Same as AMP_LINE2 + AMP_LINE_CENTER = 21, // Rectangle. (height, width and center pos + rotation) + AMP_LINE_LOWER_LEFT = 22, // Rectangle. (height, width and left bottom corner pos + rotation) + AMP_EOF = 3, // End Of File marquer: not really a shape + AMP_OUTLINE = 4, // Free polyline (n corners + rotation) + AMP_POLYGON = 5, // Closed regular polygon(diameter, number of vertices (3 to 10), rotation) + AMP_MOIRE = 6, // A cross hair with n concentric circles + rotation + AMP_THERMAL = 7 // Thermal shape (pos, outer and inner diameter, cross hair thickness + rotation) +}; + + +/** + * Struct AM_PRIMITIVE + * holds an aperture macro primitive as given in Table 3 of + * http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf + */ +class AM_PRIMITIVE +{ +public: + AM_PRIMITIVE_ID primitive_id; ///< The primitive type + AM_PARAMS params; ///< A sequence of parameters used by + // the primitive + bool m_GerbMetric; // units for this primitive: + // false = Inches, true = metric +public: AM_PRIMITIVE( bool aGerbMetric, AM_PRIMITIVE_ID aId = AMP_UNKNOWN ) + { + primitive_id = aId; + m_GerbMetric = aGerbMetric; + } + + + ~AM_PRIMITIVE() {} + + /** + * Function GetExposure + * returns the first parameter in integer form. Some but not all primitives + * use the first parameter as an exposure control. + */ + int GetExposure( GERBER_DRAW_ITEM* aParent ) const; + + /** + * Function mapExposure + * translates the first parameter from an aperture macro into a current + * exposure setting. + * @param aParent = a GERBER_DRAW_ITEM that handle: + * ** m_Exposure A dynamic setting which can change throughout the + * reading of the gerber file, and it indicates whether the current tool + * is lit or not. + * ** m_ImageNegative A dynamic setting which can change throughout the reading + * of the gerber file, and it indicates whether the current D codes are to + * be interpreted as erasures or not. + * @return true to draw with current color, false to draw with alt color (erase) + */ + bool mapExposure( GERBER_DRAW_ITEM* aParent ); + + /* Draw functions: */ + + /** + * Function DrawBasicShape + * Draw the primitive shape for flashed items. + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @param aClipBox = DC clip box (NULL is no clip) + * @param aDC = device context + * @param aColor = the normal color to use + * @param aAltColor = the color used to draw with "reverse" exposure mode (used in aperture macros only) + * @param aShapePos = the actual shape position + * @param aFilledShape = true to draw in filled mode, false to draw in skecth mode + */ + void DrawBasicShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, + EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, wxPoint aShapePos, bool aFilledShape ); + + /** GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of the shape of some primitives + * one cannot calculate the "size" of a shape (only a bounding box) + * but here, the "dimension" of the shape is the diameter of the primitive + * or for lines the width of the line + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return a dimension, or -1 if no dim to calculate + */ + int GetShapeDim( GERBER_DRAW_ITEM* aParent ); + +private: + + /** + * Function ConvertShapeToPolygon + * convert a shape to an equivalent polygon. + * Arcs and circles are approximated by segments + * Useful when a shape is not a graphic primitive (shape with hole, + * rotated shape ... ) and cannot be easily drawn. + */ + void ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector<wxPoint>& aBuffer ); +}; + + +typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES; + +/** + * Struct APERTURE_MACRO + * helps support the "aperture macro" defined within standard RS274X. + */ +struct APERTURE_MACRO +{ + wxString name; ///< The name of the aperture macro + AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs + + /* A defered parameter can be defined in aperture macro, + * but outside aperture primitives. Example + * %AMRECTHERM* + * $4=$3/2* parameter $4 is half value of parameter $3 + * m_localparamStack handle a list of local defered parameters + */ + AM_PARAMS m_localparamStack; + + /** + * function GetLocalParam + * Usually, parameters are defined inside the aperture primitive + * using immediate mode or defered mode. + * in defered mode the value is defined in a DCODE that want to use the aperture macro. + * But some parameters are defined outside the aperture primitive + * and are local to the aperture macro + * @return the value of a defered parameter defined inside the aperture macro + * @param aDcode = the D_CODE that uses this apertur macro and define defered parameters + * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate + */ + double GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const; + + /** + * Function DrawApertureMacroShape + * Draw the primitive shape for flashed items. + * When an item is flashed, this is the shape of the item + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @param aClipBox = DC clip box (NULL is no clip) + * @param aDC = device context + * @param aColor = the normal color to use + * @param aAltColor = the color used to draw with "reverse" exposure mode (used in aperture macros only) + * @param aShapePos = the actual shape position + * @param aFilledShape = true to draw in filled mode, false to draw in skecth mode + */ + void DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, + EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, wxPoint aShapePos, bool aFilledShape ); + + /** + * Function GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of a shape using many primitives + * one cannot calculate the "size" of a shape (only abounding box) + * but most of aperture macro are using one or few primitives + * and the "dimension" of the shape is the diameter of the primitive + * (or the max diameter of primitives) + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return a dimension, or -1 if no dim to calculate + */ + int GetShapeDim( GERBER_DRAW_ITEM* aParent ); + + /** + * Function HasNegativeItems + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return true if this macro has at least one shape (using aperture primitives) + * must be drawn in background color + * used to optimize screen refresh (when no items are in background color + * refresh can be faster) + */ + bool HasNegativeItems( GERBER_DRAW_ITEM* aParent ); +}; + + +/** + * Struct APERTURE_MACRO_less_than + * is used by std:set<APERTURE_MACRO> instantiation which uses + * APERTURE_MACRO.name as its key. + */ +struct APERTURE_MACRO_less_than +{ + // a "less than" test on two APERTURE_MACROs (.name wxStrings) + bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2 ) const + { + return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare + } +}; + + +/** + * Type APERTURE_MACRO_SET + * is a sorted collection of APERTURE_MACROS whose key is the name field in + * the APERTURE_MACRO. + */ +typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET; +typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR; + + +#endif // ifndef _APERTURE_MACRO_H_ diff --git a/gerbview/class_excellon.h b/gerbview/class_excellon.h new file mode 100644 index 0000000..d115d7b --- /dev/null +++ b/gerbview/class_excellon.h @@ -0,0 +1,308 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CLASS_EXCELLON_H +#define CLASS_EXCELLON_H + + +enum drill_M_code_t { + DRILL_M_UNKNOWN, + DRILL_M_END, + DRILL_M_ENDREWIND, + DRILL_M_MESSAGE, + DRILL_M_LONGMESSAGE, + DRILL_M_HEADER, + DRILL_M_ENDHEADER, + DRILL_M_BEGINPATTERN, + DRILL_M_ENDPATTERN, + DRILL_M_CANNEDTEXT, + DRILL_M_TIPCHECK, + DRILL_M_METRIC, + DRILL_M_IMPERIAL, + DRILL_METRICHEADER, + DRILL_IMPERIALHEADER, + DRILL_DETECT_BROKEN, + DRILL_INCREMENTALHEADER, + DRILL_REWIND_STOP, + DRILL_TOOL_CHANGE_STOP, + DRILL_AUTOMATIC_SPEED, + DRILL_AXIS_VERSION, + DRILL_RESET_CMD, + DRILL_AUTOMATIC_TOOL_CHANGE, + DRILL_FMT, + DRILL_SKIP, + DRILL_TOOL_INFORMATION +}; + + +enum drill_G_code_t { + DRILL_G_UNKNOWN, + DRILL_G_ABSOLUTE, + DRILL_G_INCREMENTAL, + DRILL_G_ZEROSET, + DRILL_G_ROUT, + DRILL_G_DRILL, + DRILL_G_SLOT, + DRILL_G_ZERO_SET, + DRILL_G_LINEARMOVE, + DRILL_G_CWMOVE, + DRILL_G_CCWMOVE +}; + +// Helper struct to analyse Excellon commands +struct EXCELLON_CMD +{ + std::string m_Name; // key string + int m_Code; // internal code, used as id in functions + int m_asParams; // 0 = no param, -1 = skip params, 1 = read params +}; + + +/* EXCELLON_IMAGE handle a drill image + * It is derived from GERBER_IMAGE because there is a lot of likeness + * between EXCELLON files and GERBER files + * DCode aperture are also similat to T Codes. + * So we can reuse GERBER_IMAGE to handle EXCELLON_IMAGE with very few new functions + */ + +class EXCELLON_IMAGE : public GERBER_IMAGE +{ +private: + enum excellon_state { + READ_HEADER_STATE, // When we are in this state, we are reading header + READ_PROGRAM_STATE // When we are in this state, we are reading drill data + }; + excellon_state m_State; // state of excellon file analysis + bool m_SlotOn; // true during an oval driil definition + +public: EXCELLON_IMAGE( GERBVIEW_FRAME* aParent, int layer ) : + GERBER_IMAGE( aParent, layer ) + { + m_State = READ_HEADER_STATE; + m_SlotOn = false; + } + + + ~EXCELLON_IMAGE() {}; + + virtual void ResetDefaultValues() + { + GERBER_IMAGE::ResetDefaultValues(); + SelectUnits( false ); + } + + + bool Read_EXCELLON_File( FILE* aFile, const wxString& aFullFileName ); + +private: + bool Execute_HEADER_Command( char*& text ); + bool Select_Tool( char*& text ); + bool Execute_EXCELLON_G_Command( char*& text ); + bool Execute_Drill_Command( char*& text ); + + int TCodeNumber( char*& Text ) + { + return DCodeNumber( Text ); + } + + + void SelectUnits( bool aMetric ); +}; + + +/* + * EXCELLON commands are given here. + * Pcbnew uses only few excellon commands + */ + +/* + * see http://www.excellon.com/manuals/program.htm + */ + +/* coordintes units: + * Coordinates are measured either in inch or metric (millimeters). + * Inch coordinates are in six digits (00.0000) with increments as small as 0.0001 (1/10,000). + * Metric coordinates can be measured in microns (thousandths of a millimeter) + * in one of the following three ways: + * Five digit 10 micron resolution (000.00) + * Six digit 10 micron resolution (0000.00) + * Six digit micron resolution (000.000) + * + * Leading and trailing zeros: + * Excellon (CNC-7) uses inches in six digits and metric in five or six digits. + * The zeros to the left of the coordinate are called leading zeros (LZ). + * The zeros to right of the coordinate are called trailing zeros (TZ). + * The CNC-7 uses leading zeros unless you specify otherwise through a part program. + * You can do so with the INCH/METRIC command. + * With leading zeros, the leading zeros must always be included. + * Trailing zeros are unneeded and may be left off. + * For trailing zeros, the reverse of the above is true. + */ + +/* + * EXCELLON Commands Used in a Header + * The following table provides you with a list of commands which + * are the most used in a part program header. + * COMMAND DESCRIPTION + * AFS Automatic Feeds and Speeds + * ATC Automatic Tool Change + * BLKD Delete all Blocks starting with a slash (/) + * CCW Clockwise or Counter-clockwise Routing + * CP Cutter Compensation + * DETECT Broken Tool Detection + * DN Down Limit Set + * DTMDIST Maximum Rout Distance Before Toolchange + * EXDA Extended Drill Area + * FMAT Format 1 or 2 + * FSB Turns the Feed/Speed Buttons off + * HPCK Home Pulse Check + * ICI Incremental Input of Part Program Coordinates + * INCH Measure Everything in Inches + * METRIC Measure Everything in Metric + * M48 Beginning of Part Program Header + * M95 End of Header + * NCSL NC Slope Enable/Disable + * OM48 Override Part Program Header + * OSTOP Optional Stop Switch + * OTCLMP Override Table Clamp + * PCKPARAM Set up pecking tool,depth,infeed and retract parameters + * PF Floating Pressure Foot Switch + * PPR Programmable Plunge Rate Enable + * PVS Pre-vacuum Shut-off Switch + * R,C Reset Clocks + * R,CP Reset Program Clocks + * R,CR Reset Run Clocks + * R,D Reset All Cutter Distances + * R,H Reset All Hit Counters + * R,T Reset Tool Data + * SBK Single Block Mode Switch + * SG Spindle Group Mode + * SIXM Input From External Source + * T Tool Information + * TCST Tool Change Stop + * UP Upper Limit Set + * VER Selection of X and Y Axis Version + * Z Zero Set + * ZA Auxiliary Zero + * ZC Zero Correction + * ZS Zero Preset + * Z+# or Z-# Set Depth Offset + * % Rewind Stop + * #/#/# Link Tool for Automatic Tool Change + * / Clear Tool Linking + */ + +/* + * Beyond The Header: The Part Program Body + * COMMAND DESCRIPTION + * A# Arc Radius + * B# Retract Rate + * C# Tool Diameter + * F# Table Feed Rate;Z Axis Infeed Rate + * G00X#Y# Route Mode + * G01 Linear (Straight Line) Mode + * G02 Circular CW Mode + * G03 Circular CCW Mode + * G04 X# Variable Dwell + * G05 Drill Mode + * G07 Override current tool feed or speed + * G32X#Y#A# Routed Circle Canned Cycle + * CW G33X#Y#A# Routed Circle Canned Cycle + * CCW G34,#(,#) Select Vision Tool + * G35(X#Y#) Single Point Vision Offset (Relative to Work Zero) + * G36(X#Y#) Multipoint Vision Translation (Relative to Work Zero) + * G37 Cancel Vision Translation or Offset (From G35 or G36) + * G38(X#Y#) Vision Corrected Single Hole Drilling (Relative to Work Zero) + * G39(X#Y#) Vision System Autocalibration + * G40 Cutter Compensation Off + * G41 Cutter Compensation Left + * G42 Cutter Compensation Right + * G45(X#Y#) Single Point Vision Offset (Relative to G35 or G36) + * G46(X#Y#) Multipoint Vision Translation (Relative to G35 or G36) + * G47 Cancel Vision Translation or Offset (From G45 or G46) + * G48(X#Y#) Vision Corrected Single Hole Drilling (Relative to G35 or G36) + * G82(G81) Dual In Line Package + * G83 Eight Pin L Pack + * G84 Circle + * G85 Slot + * G87 Routed Step Slot Canned Cycle + * G90 Absolute Mode + * G91 Incremental Input Mode + * G93X#Y# Zero Set + * H# Maximum hit count + * I#J# Arc Center Offset + * M00(X#Y#) End of Program - No Rewind + * M01 End of Pattern + * M02X#Y# Repeat Pattern Offset + * M06(X#Y#) Optional Stop + * M08 End of Step and Repeat + * M09(X#Y#) Stop for Inspection + * M14 Z Axis Route Position With Depth Controlled Contouring + * M15 Z Axis Route Position + * M16 Retract With Clamping + * M17 Retract Without Clamping + * M18 Command tool tip check + * M25 Beginning of Pattern + * M30(X#Y#) End of Program Rewind + * M45,long message\ Long Operator message on multiple\ part program lines + * M47,text Operator Message + * M50,# Vision Step and Repeat Pattern Start + * M51,# Vision Step and Repeat Rewind + * M52(#) Vision Step and Repeat Offset Counter Control + * M02XYM70 Swap Axes + * M60 Reference Scaling enable + * M61 Reference Scaling disable + * M62 Turn on peck drilling + * M63 Turn off peck drilling + * M71 Metric Measuring Mode + * M72 Inch Measuring Mode + * M02XYM80 Mirror Image X Axis + * M02XYM90 Mirror Image Y Axis + * M97,text Canned Text + * M98,text Canned Text + * M99,subprogram User Defined Stored Pattern + * P#X#(Y#) Repeat Stored Pattern + * R#M02X#Y# Repeat Pattern (S&R) + * R#(X#Y#) Repeat Hole + * S# Spindle RPM + * T# Tool Selection; Cutter Index + * Z+# or Z-# Depth Offset + * % Beginning of Pattern (see M25 command) + * / Block Delete + */ + +/* + * Example of a Header + * COMMAND PURPOSE + * M48 The beginning of a header + * INCH,LZ Use the inch measuring system with leading zeros + * VER,1 Use Version 1 X and Y axis layout + * FMAT,2 Use Format 2 commands + * 1/2/3 Link tools 1, 2, and 3 + * T1C.04F200S65 Set Tool 1 for 0.040" with infeed rate of 200 inch/min Speed of 65,000 RPM + * DETECT,ON Detect broken tools + * M95 End of the header + */ + +#endif // CLASS_EXCELLON_H diff --git a/gerbview/class_gbr_layer_box_selector.cpp b/gerbview/class_gbr_layer_box_selector.cpp new file mode 100644 index 0000000..f148306 --- /dev/null +++ b/gerbview/class_gbr_layer_box_selector.cpp @@ -0,0 +1,81 @@ +/** + * @file class_gbr_layer_box_selector.cpp + * @brief a derived class of LAYER_BOX_SELECTOR to handle the layer box selector + * in GerbView + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 Jean-Pierre Charras <jean-pierre.charras@ujf-grenoble.fr> + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <common.h> +#include <colors_selection.h> +#include <layers_id_colors_and_visibility.h> +#include <gerbview_frame.h> +#include <class_GERBER.h> +#include <class_X2_gerber_attributes.h> + +#include <class_gbr_layer_box_selector.h> + +void GBR_LAYER_BOX_SELECTOR::Resync() +{ + Freeze(); + Clear(); + + for( int layerid = 0; layerid < GERBER_DRAWLAYERS_COUNT; ++layerid ) + { + wxBitmap layerbmp( 14, 14 ); + wxString layername; + + if( !IsLayerEnabled( layerid ) ) + continue; + + // Prepare Bitmap + SetBitmapLayer( layerbmp, layerid ); + + layername = GetLayerName( layerid ); + + Append( layername, layerbmp, (void*)(intptr_t) layerid ); + } + + Thaw(); +} + + +// Returns a color index from the layer id +EDA_COLOR_T GBR_LAYER_BOX_SELECTOR::GetLayerColor( int aLayer ) const +{ + GERBVIEW_FRAME* frame = (GERBVIEW_FRAME*) GetParent()->GetParent(); + + return frame->GetLayerColor( aLayer ); +} + + +// Returns the name of the layer id +wxString GBR_LAYER_BOX_SELECTOR::GetLayerName( int aLayer ) const +{ + wxString name = g_GERBER_List.GetDisplayName( aLayer ); + + return name; +} diff --git a/gerbview/class_gbr_layer_box_selector.h b/gerbview/class_gbr_layer_box_selector.h new file mode 100644 index 0000000..6128bce --- /dev/null +++ b/gerbview/class_gbr_layer_box_selector.h @@ -0,0 +1,59 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CLASS_GBR_LAYER_BOX_SELECTOR_H +#define CLASS_GBR_LAYER_BOX_SELECTOR_H 1 + +#include <class_layer_box_selector.h> + + +// class to display a layer list in GerbView. +class GBR_LAYER_BOX_SELECTOR : public LAYER_BOX_SELECTOR +{ +public: + GBR_LAYER_BOX_SELECTOR( wxWindow* parent, wxWindowID id, + const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = NULL ) : + LAYER_BOX_SELECTOR( parent, id, pos, size, n, choices ) + { + m_layerhotkeys = false; + } + + // Reload the Layers names and bitmaps + // Virtual function + void Resync(); + + // Returns a color index from the layer id + // Virtual function + EDA_COLOR_T GetLayerColor( int aLayer ) const; + + // Returns true if the layer id is enabled (i.e. is it should be displayed) + // Virtual function + bool IsLayerEnabled( int aLayer ) const { return true; }; + + // Returns the name of the layer id + wxString GetLayerName( int aLayer ) const; +}; + +#endif //CLASS_GBR_LAYER_BOX_SELECTOR_H diff --git a/gerbview/class_gbr_layout.cpp b/gerbview/class_gbr_layout.cpp new file mode 100644 index 0000000..427cab1 --- /dev/null +++ b/gerbview/class_gbr_layout.cpp @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gbr_layout.cpp + * @brief GBR_LAYOUT class functions. + */ + +#include <limits.h> +#include <algorithm> + +#include <fctsys.h> +#include <common.h> +#include <class_gbr_layout.h> + +GBR_LAYOUT::GBR_LAYOUT() +{ + m_printLayersMask.set(); +} + + +GBR_LAYOUT::~GBR_LAYOUT() +{ +} + + +EDA_RECT GBR_LAYOUT::ComputeBoundingBox() +{ + EDA_RECT bbox; + + for( GERBER_DRAW_ITEM* gerb_item = m_Drawings; gerb_item; gerb_item = gerb_item->Next() ) + bbox.Merge( gerb_item->GetBoundingBox() ); + + SetBoundingBox( bbox ); + return bbox; +} diff --git a/gerbview/class_gbr_layout.h b/gerbview/class_gbr_layout.h new file mode 100644 index 0000000..e5610ec --- /dev/null +++ b/gerbview/class_gbr_layout.h @@ -0,0 +1,148 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gbr_layout.h + * @brief Class CLASS_GBR_LAYOUT to handle info to draw/print loaded Gerber images + * and page frame reference + */ + +#ifndef CLASS_GBR_LAYOUT_H +#define CLASS_GBR_LAYOUT_H + + +#include <dlist.h> + +#include <class_colors_design_settings.h> +#include <common.h> // PAGE_INFO +#include <gerbview.h> // GERBER_DRAWLAYERS_COUNT +#include <class_title_block.h> +#include <class_gerber_draw_item.h> + +#include <gr_basic.h> + +/** + * Class GBR_LAYOUT + * holds list of GERBER_DRAW_ITEM currently loaded. + */ +class GBR_LAYOUT +{ +private: + EDA_RECT m_BoundingBox; + TITLE_BLOCK m_titles; + wxPoint m_originAxisPosition; + std::bitset <GERBER_DRAWLAYERS_COUNT> m_printLayersMask; // When printing: the list of layers to print +public: + + DLIST<GERBER_DRAW_ITEM> m_Drawings; // linked list of Gerber Items to draw + + GBR_LAYOUT(); + ~GBR_LAYOUT(); + + const wxPoint& GetAuxOrigin() const + { + return m_originAxisPosition; + } + + void SetAuxOrigin( const wxPoint& aPosition ) + { + m_originAxisPosition = aPosition; + } + + TITLE_BLOCK& GetTitleBlock() + { + return m_titles; + } + + void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) + { + m_titles = aTitleBlock; + } + + /** + * Function ComputeBoundingBox + * calculates the bounding box containing all Gerber items. + * @return EDA_RECT - the full item list bounding box + */ + EDA_RECT ComputeBoundingBox(); + + /** + * Function GetBoundingBox + * may be called soon after ComputeBoundingBox() to return the same EDA_RECT, + * as long as the CLASS_GBR_LAYOUT has not changed. + */ + EDA_RECT GetBoundingBox() const { return m_BoundingBox; } // override + + void SetBoundingBox( const EDA_RECT& aBox ) { m_BoundingBox = aBox; } + + /** + * Function Draw. + * Redraw the CLASS_GBR_LAYOUT items but not cursors, axis or grid. + * @param aPanel = the panel relative to the board + * @param aDC = the current device context + * @param aDrawMode = GR_COPY, GR_OR ... (not always used) + * @param aOffset = an draw offset value + * @param aPrintBlackAndWhite = true to force black and white insdeat of color + * useful only to print/plot gebview layers + */ + void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, + GR_DRAWMODE aDrawMode, const wxPoint& aOffset, + bool aPrintBlackAndWhite = false ); + /** + * Function SetPrintableLayers + * changes the list of printable layers + * @param aLayerMask = The new bit-mask of printable layers + */ + void SetPrintableLayers( const std::bitset <GERBER_DRAWLAYERS_COUNT>& aLayerMask ) + { + m_printLayersMask = aLayerMask; + } + + /** + * Function GetPrintableLayers + * @return the bit-mask of printable layers + */ + std::bitset <GERBER_DRAWLAYERS_COUNT> GetPrintableLayers() + { + return m_printLayersMask; + } + + /** + * Function IsLayerPrintable + * tests whether a given layer is visible + * @param aLayer = The layer to be tested + * @return bool - true if the layer is visible. + */ + bool IsLayerPrintable( int aLayer ) const + { + return m_printLayersMask[ aLayer ]; + } + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const; // overload + +#endif +}; + +#endif // #ifndef CLASS_GBR_LAYOUT_H diff --git a/gerbview/class_gbr_screen.cpp b/gerbview/class_gbr_screen.cpp new file mode 100644 index 0000000..2cd2e7f --- /dev/null +++ b/gerbview/class_gbr_screen.cpp @@ -0,0 +1,143 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gbr_screen.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <macros.h> +#include <class_gbr_screen.h> +#include <base_units.h> +#include <gerbview_id.h> + +#define DMIL_GRID( x ) wxRealPoint( x * IU_PER_DECIMILS,\ + x * IU_PER_DECIMILS ) +#define MM_GRID( x ) wxRealPoint( x * IU_PER_MM,\ + x * IU_PER_MM ) + + +/** + Default GerbView zoom values. + Roughly a 1.5 progression. +*/ +static const double gbrZoomList[] = +{ + ZOOM_FACTOR( 0.5 ), + ZOOM_FACTOR( 0.75 ), + ZOOM_FACTOR( 1.0 ), + ZOOM_FACTOR( 1.5 ), + ZOOM_FACTOR( 2.0 ), + ZOOM_FACTOR( 3.0 ), + ZOOM_FACTOR( 4.5 ), + ZOOM_FACTOR( 7.0 ), + ZOOM_FACTOR( 10.0 ), + ZOOM_FACTOR( 15.0 ), + ZOOM_FACTOR( 22.0 ), + ZOOM_FACTOR( 35.0 ), + ZOOM_FACTOR( 50.0 ), + ZOOM_FACTOR( 80.0 ), + ZOOM_FACTOR( 110.0 ), + ZOOM_FACTOR( 150.0 ), + ZOOM_FACTOR( 200.0 ), + ZOOM_FACTOR( 350.0 ), + ZOOM_FACTOR( 500.0 ), + ZOOM_FACTOR( 1000.0 ), + ZOOM_FACTOR( 2000.0 ) +}; + + +// Default grid sizes for PCB editor screens. +static GRID_TYPE gbrGridList[] = +{ + // predefined grid list in 0.0001 inches + { ID_POPUP_GRID_LEVEL_1000, DMIL_GRID( 1000 ) }, + { ID_POPUP_GRID_LEVEL_500, DMIL_GRID( 500 ) }, + { ID_POPUP_GRID_LEVEL_250, DMIL_GRID( 250 ) }, + { ID_POPUP_GRID_LEVEL_200, DMIL_GRID( 200 ) }, + { ID_POPUP_GRID_LEVEL_100, DMIL_GRID( 100 ) }, + { ID_POPUP_GRID_LEVEL_50, DMIL_GRID( 50 ) }, + { ID_POPUP_GRID_LEVEL_25, DMIL_GRID( 25 ) }, + { ID_POPUP_GRID_LEVEL_20, DMIL_GRID( 20 ) }, + { ID_POPUP_GRID_LEVEL_10, DMIL_GRID( 10 ) }, + { ID_POPUP_GRID_LEVEL_5, DMIL_GRID( 5 ) }, + { ID_POPUP_GRID_LEVEL_2, DMIL_GRID( 2 ) }, + { ID_POPUP_GRID_LEVEL_1, DMIL_GRID( 1 ) }, + + // predefined grid list in mm + { ID_POPUP_GRID_LEVEL_5MM, MM_GRID( 5.0 ) }, + { ID_POPUP_GRID_LEVEL_2_5MM, MM_GRID( 2.5 ) }, + { ID_POPUP_GRID_LEVEL_1MM, MM_GRID( 1.0 ) }, + { ID_POPUP_GRID_LEVEL_0_5MM, MM_GRID( 0.5 ) }, + { ID_POPUP_GRID_LEVEL_0_25MM, MM_GRID( 0.25 ) }, + { ID_POPUP_GRID_LEVEL_0_2MM, MM_GRID( 0.2 ) }, + { ID_POPUP_GRID_LEVEL_0_1MM, MM_GRID( 0.1 ) }, + { ID_POPUP_GRID_LEVEL_0_0_5MM, MM_GRID( 0.05 ) }, + { ID_POPUP_GRID_LEVEL_0_0_25MM, MM_GRID( 0.025 ) }, + { ID_POPUP_GRID_LEVEL_0_0_1MM, MM_GRID( 0.01 ) } +}; + + +GBR_SCREEN::GBR_SCREEN( const wxSize& aPageSizeIU ) : + BASE_SCREEN( SCREEN_T ) +{ + for( unsigned i = 0; i < DIM( gbrZoomList ); ++i ) + m_ZoomList.push_back( gbrZoomList[i] ); + + for( unsigned i = 0; i < DIM( gbrGridList ); ++i ) + AddGrid( gbrGridList[i] ); + + // Set the working grid size to a reasonable value (in 1/10000 inch) + SetGrid( DMIL_GRID( 500 ) ); + + m_Active_Layer = B_Cu; // default active layer = bottom layer + + SetZoom( ZOOM_FACTOR( 350 ) ); // a default value for zoom + + InitDataPoints( aPageSizeIU ); +} + + +GBR_SCREEN::~GBR_SCREEN() +{ + ClearUndoRedoList(); +} + + +// virtual function +int GBR_SCREEN::MilsToIuScalar() +{ + return (int)IU_PER_MILS; +} + + +/* Virtual function needed by classes derived from BASE_SCREEN + * this is a virtual pure function in BASE_SCREEN + * do nothing in GerbView + * could be removed later + */ +void GBR_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER&, int ) +{ +} diff --git a/gerbview/class_gbr_screen.h b/gerbview/class_gbr_screen.h new file mode 100644 index 0000000..19b5f90 --- /dev/null +++ b/gerbview/class_gbr_screen.h @@ -0,0 +1,69 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gbr_screen.h + */ + +#ifndef CLASS_GBR_SCREEN_H_ +#define CLASS_GBR_SCREEN_H_ + + +#include <base_units.h> +#include <class_base_screen.h> +#include <layers_id_colors_and_visibility.h> + +#define ZOOM_FACTOR( x ) ( x * IU_PER_DECIMILS ) + + +/* Handle info to display a board */ +class GBR_SCREEN : public BASE_SCREEN +{ +public: + LAYER_NUM m_Active_Layer; + /** + * Constructor + * @param aPageSizeIU is the size of the initial paper page in internal units. + */ + GBR_SCREEN( const wxSize& aPageSizeIU ); + + ~GBR_SCREEN(); + + GBR_SCREEN* Next() const { return static_cast<GBR_SCREEN*>( Pnext ); } + +// void SetNextZoom(); +// void SetPreviousZoom(); +// void SetLastZoom(); + + virtual int MilsToIuScalar(); + + /** + * Function ClearUndoORRedoList + * virtual pure in BASE_SCREEN, so it must be defined here + */ + void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 ); +}; + + +#endif // CLASS_GBR_SCREEN_H_ diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp new file mode 100644 index 0000000..b915395 --- /dev/null +++ b/gerbview/class_gerber_draw_item.cpp @@ -0,0 +1,631 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 <Jean-Pierre Charras> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gerber_draw_item.cpp + */ + +#include <fctsys.h> +#include <gr_basic.h> +#include <common.h> +#include <trigo.h> +#include <class_drawpanel.h> +#include <macros.h> +#include <msgpanel.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> + + +GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( GBR_LAYOUT* aParent, GERBER_IMAGE* aGerberparams ) : + EDA_ITEM( (EDA_ITEM*)aParent, TYPE_GERBER_DRAW_ITEM ) +{ + m_imageParams = aGerberparams; + m_Layer = 0; + m_Shape = GBR_SEGMENT; + m_Flashed = false; + m_DCode = 0; + m_UnitsMetric = false; + m_LayerNegative = false; + m_swapAxis = false; + m_mirrorA = false; + m_mirrorB = false; + m_drawScale.x = m_drawScale.y = 1.0; + m_lyrRotation = 0; + if( m_imageParams ) + SetLayerParameters(); +} + + +// Copy constructor +GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) : + EDA_ITEM( aSource ) +{ + m_imageParams = aSource.m_imageParams; + m_Shape = aSource.m_Shape; + + m_Flags = aSource.m_Flags; + SetTimeStamp( aSource.m_TimeStamp ); + + SetStatus( aSource.GetStatus() ); + m_Start = aSource.m_Start; + m_End = aSource.m_End; + m_Size = aSource.m_Size; + m_Layer = aSource.m_Layer; + m_Shape = aSource.m_Shape; + m_Flashed = aSource.m_Flashed; + m_DCode = aSource.m_DCode; + m_PolyCorners = aSource.m_PolyCorners; + m_UnitsMetric = aSource.m_UnitsMetric; + m_LayerNegative = aSource.m_LayerNegative; + m_swapAxis = aSource.m_swapAxis; + m_mirrorA = aSource.m_mirrorA; + m_mirrorB = aSource.m_mirrorB; + m_layerOffset = aSource.m_layerOffset; + m_drawScale = aSource.m_drawScale; + m_lyrRotation = aSource.m_lyrRotation; +} + + +GERBER_DRAW_ITEM::~GERBER_DRAW_ITEM() +{ +} + + +GERBER_DRAW_ITEM* GERBER_DRAW_ITEM::Copy() const +{ + return new GERBER_DRAW_ITEM( *this ); +} + + +wxPoint GERBER_DRAW_ITEM::GetABPosition( const wxPoint& aXYPosition ) const +{ + /* Note: RS274Xrevd_e is obscure about the order of transforms: + * For instance: Rotation must be made after or before mirroring ? + * Note: if something is changed here, GetYXPosition must reflect changes + */ + wxPoint abPos = aXYPosition + m_imageParams->m_ImageJustifyOffset; + + if( m_swapAxis ) + std::swap( abPos.x, abPos.y ); + + abPos += m_layerOffset + m_imageParams->m_ImageOffset; + abPos.x = KiROUND( abPos.x * m_drawScale.x ); + abPos.y = KiROUND( abPos.y * m_drawScale.y ); + double rotation = m_lyrRotation * 10 + m_imageParams->m_ImageRotation * 10; + + if( rotation ) + RotatePoint( &abPos, -rotation ); + + // Negate A axis if mirrored + if( m_mirrorA ) + abPos.x = -abPos.x; + + // abPos.y must be negated when no mirror, because draw axis is top to bottom + if( !m_mirrorB ) + abPos.y = -abPos.y; + return abPos; +} + + +wxPoint GERBER_DRAW_ITEM::GetXYPosition( const wxPoint& aABPosition ) const +{ + // do the inverse transform made by GetABPosition + wxPoint xyPos = aABPosition; + + if( m_mirrorA ) + xyPos.x = -xyPos.x; + + if( !m_mirrorB ) + xyPos.y = -xyPos.y; + + double rotation = m_lyrRotation * 10 + m_imageParams->m_ImageRotation * 10; + + if( rotation ) + RotatePoint( &xyPos, rotation ); + + xyPos.x = KiROUND( xyPos.x / m_drawScale.x ); + xyPos.y = KiROUND( xyPos.y / m_drawScale.y ); + xyPos -= m_layerOffset + m_imageParams->m_ImageOffset; + + if( m_swapAxis ) + std::swap( xyPos.x, xyPos.y ); + + return xyPos - m_imageParams->m_ImageJustifyOffset; +} + + +void GERBER_DRAW_ITEM::SetLayerParameters() +{ + m_UnitsMetric = m_imageParams->m_GerbMetric; + m_swapAxis = m_imageParams->m_SwapAxis; // false if A = X, B = Y; + + // true if A =Y, B = Y + m_mirrorA = m_imageParams->m_MirrorA; // true: mirror / axe A + m_mirrorB = m_imageParams->m_MirrorB; // true: mirror / axe B + m_drawScale = m_imageParams->m_Scale; // A and B scaling factor + m_layerOffset = m_imageParams->m_Offset; // Offset from OF command + + // Rotation from RO command: + m_lyrRotation = m_imageParams->m_LocalRotation; + m_LayerNegative = m_imageParams->GetLayerParams().m_LayerNegative; +} + + +wxString GERBER_DRAW_ITEM::ShowGBRShape() +{ + switch( m_Shape ) + { + case GBR_SEGMENT: + return _( "Line" ); + + case GBR_ARC: + return _( "Arc" ); + + case GBR_CIRCLE: + return _( "Circle" ); + + case GBR_SPOT_OVAL: + return wxT( "spot_oval" ); + + case GBR_SPOT_CIRCLE: + return wxT( "spot_circle" ); + + case GBR_SPOT_RECT: + return wxT( "spot_rect" ); + + case GBR_SPOT_POLY: + return wxT( "spot_poly" ); + + case GBR_POLYGON: + return wxT( "polygon" ); + + case GBR_SPOT_MACRO: + { + wxString name = wxT( "apt_macro" ); + D_CODE* dcode = GetDcodeDescr(); + + if( dcode && dcode->GetMacro() ) + name << wxT(" ") << dcode->GetMacro()->name; + + return name; + } + + default: + return wxT( "??" ); + } +} + + +D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr() +{ + if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) ) + return NULL; + + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( m_Layer ); + + if( gerber == NULL ) + return NULL; + + D_CODE* d_code = gerber->GetDCODE( m_DCode, false ); + + return d_code; +} + + +const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const +{ + // return a rectangle which is (pos,dim) in nature. therefore the +1 + EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); + + bbox.Inflate( m_Size.x / 2, m_Size.y / 2 ); + + bbox.SetOrigin( GetABPosition( bbox.GetOrigin() ) ); + bbox.SetEnd( GetABPosition( bbox.GetEnd() ) ); + return bbox; +} + + +void GERBER_DRAW_ITEM::MoveAB( const wxPoint& aMoveVector ) +{ + wxPoint xymove = GetXYPosition( aMoveVector ); + + m_Start += xymove; + m_End += xymove; + m_ArcCentre += xymove; + + for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) + m_PolyCorners[ii] += xymove; +} + + +void GERBER_DRAW_ITEM::MoveXY( const wxPoint& aMoveVector ) +{ + m_Start += aMoveVector; + m_End += aMoveVector; + m_ArcCentre += aMoveVector; + + for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) + m_PolyCorners[ii] += aMoveVector; +} + + +bool GERBER_DRAW_ITEM::Save( FILE* aFile ) const +{ + return true; +} + +bool GERBER_DRAW_ITEM::HasNegativeItems() +{ + bool isClear = m_LayerNegative ^ m_imageParams->m_ImageNegative; + + // if isClear is true, this item has negative shape + // but if isClear is true, and if this item use an aperture macro definition, + // we must see if this aperture macro uses a negative shape. + if( isClear ) + return true; + + // see for a macro def + D_CODE* dcodeDescr = GetDcodeDescr(); + + if( dcodeDescr == NULL ) + return false; + + if( m_Shape == GBR_SPOT_MACRO ) + { + APERTURE_MACRO* macro = dcodeDescr->GetMacro(); + + if( macro ) // macro == NULL should not occurs + return macro->HasNegativeItems( this ); + } + + return false; +} + + +void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, + const wxPoint& aOffset ) +{ + // used when a D_CODE is not found. default D_CODE to draw a flashed item + static D_CODE dummyD_CODE( 0 ); + EDA_COLOR_T color, alt_color; + bool isFilled; + int radius; + int halfPenWidth; + static bool show_err; + D_CODE* d_codeDescr = GetDcodeDescr(); + GERBVIEW_FRAME* gerbFrame = (GERBVIEW_FRAME*) aPanel->GetParent(); + + if( d_codeDescr == NULL ) + d_codeDescr = &dummyD_CODE; + + if( gerbFrame->IsLayerVisible( GetLayer() ) == false ) + return; + + color = gerbFrame->GetLayerColor( GetLayer() ); + + if( aDrawMode & GR_HIGHLIGHT ) + ColorChangeHighlightFlag( &color, !(aDrawMode & GR_AND) ); + + ColorApplyHighlightFlag( &color ); + + alt_color = gerbFrame->GetNegativeItemsColor(); + + /* isDark is true if flash is positive and should use a drawing + * color other than the background color, else use the background color + * when drawing so that an erasure happens. + */ + bool isDark = !(m_LayerNegative ^ m_imageParams->m_ImageNegative); + + if( !isDark ) + { + // draw in background color ("negative" color) + std::swap( color, alt_color ); + } + + GRSetDrawMode( aDC, aDrawMode ); + + isFilled = gerbFrame->DisplayLinesSolidMode(); + + switch( m_Shape ) + { + case GBR_POLYGON: + isFilled = gerbFrame->DisplayPolygonsSolidMode(); + + if( !isDark ) + isFilled = true; + + DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled ); + break; + + case GBR_CIRCLE: + radius = KiROUND( GetLineLength( m_Start, m_End ) ); + + halfPenWidth = m_Size.x >> 1; + + if( !isFilled ) + { + // draw the border of the pen's path using two circles, each as narrow as possible + GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + radius - halfPenWidth, 0, color ); + GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + radius + halfPenWidth, 0, color ); + } + else // Filled mode + { + GRCircle( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + radius, m_Size.x, color ); + } + break; + + case GBR_ARC: + // Currently, arcs plotted with a rectangular aperture are not supported. + // a round pen only is expected. + +#if 0 // for arc debug only + GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + GetABPosition( m_ArcCentre ), 0, color ); + GRLine( aPanel->GetClipBox(), aDC, GetABPosition( m_End ), + GetABPosition( m_ArcCentre ), 0, color ); +#endif + + if( !isFilled ) + { + GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + GetABPosition( m_End ), GetABPosition( m_ArcCentre ), + 0, color ); + } + else + { + GRArc1( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + GetABPosition( m_End ), GetABPosition( m_ArcCentre ), + m_Size.x, color ); + } + + break; + + case GBR_SPOT_CIRCLE: + case GBR_SPOT_RECT: + case GBR_SPOT_OVAL: + case GBR_SPOT_POLY: + case GBR_SPOT_MACRO: + isFilled = gerbFrame->DisplayFlashedItemsSolidMode(); + d_codeDescr->DrawFlashedShape( this, aPanel->GetClipBox(), aDC, color, alt_color, + m_Start, isFilled ); + break; + + case GBR_SEGMENT: + /* Plot a line from m_Start to m_End. + * Usually, a round pen is used, but some gerber files use a rectangular pen + * In fact, any aperture can be used to plot a line. + * currently: only a square pen is handled (I believe using a polygon gives a strange plot). + */ + if( d_codeDescr->m_Shape == APT_RECT ) + { + if( m_PolyCorners.size() == 0 ) + ConvertSegmentToPolygon( ); + + DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled ); + } + else + { + if( !isFilled ) + { + GRCSegm( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + GetABPosition( m_End ), m_Size.x, color ); + } + else + { + GRFilledSegment( aPanel->GetClipBox(), aDC, GetABPosition( m_Start ), + GetABPosition( m_End ), m_Size.x, color ); + } + } + + break; + + default: + if( !show_err ) + { + wxMessageBox( wxT( "Trace_Segment() type error" ) ); + show_err = true; + } + + break; + } +} + + +void GERBER_DRAW_ITEM::ConvertSegmentToPolygon( ) +{ + m_PolyCorners.clear(); + m_PolyCorners.reserve(6); + + wxPoint start = m_Start; + wxPoint end = m_End; + + // make calculations more easy if ensure start.x < end.x + // (only 2 quadrants to consider) + if( start.x > end.x ) + std::swap( start, end ); + + // calculate values relative to start point: + wxPoint delta = end - start; + + // calculate corners for the first quadrant only (delta.x and delta.y > 0 ) + // currently, delta.x already is > 0. + // make delta.y > 0 + bool change = delta.y < 0; + + if( change ) + delta.y = -delta.y; + + // Now create the full polygon. + // Due to previous changes, the shape is always something like + // 3 4 + // 2 5 + // 1 6 + wxPoint corner; + corner.x -= m_Size.x/2; + corner.y -= m_Size.y/2; + m_PolyCorners.push_back( corner ); // Lower left corner, start point (1) + corner.y += m_Size.y; + m_PolyCorners.push_back( corner ); // upper left corner, start point (2) + + if( delta.x || delta.y) + { + corner += delta; + m_PolyCorners.push_back( corner ); // upper left corner, end point (3) + } + + corner.x += m_Size.x; + m_PolyCorners.push_back( corner ); // upper right corner, end point (4) + corner.y -= m_Size.y; + m_PolyCorners.push_back( corner ); // lower right corner, end point (5) + + if( delta.x || delta.y ) + { + corner -= delta; + m_PolyCorners.push_back( corner ); // lower left corner, start point (6) + } + + // Create final polygon: + for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) + { + if( change ) + m_PolyCorners[ii].y = -m_PolyCorners[ii].y; + + m_PolyCorners[ii] += start; + } +} + + +void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_RECT* aClipBox, + wxDC* aDC, + EDA_COLOR_T aColor, + const wxPoint& aOffset, + bool aFilledShape ) +{ + std::vector<wxPoint> points; + + points = m_PolyCorners; + for( unsigned ii = 0; ii < points.size(); ii++ ) + { + points[ii] += aOffset; + points[ii] = GetABPosition( points[ii] ); + } + + GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilledShape, aColor, aColor ); +} + + +void GERBER_DRAW_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) +{ + wxString msg; + + msg = ShowGBRShape(); + aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, DARKCYAN ) ); + + // Display D_Code value: + msg.Printf( wxT( "%d" ), m_DCode ); + aList.push_back( MSG_PANEL_ITEM( _( "D Code" ), msg, RED ) ); + + // Display graphic layer number + msg.Printf( wxT( "%d" ), GetLayer() + 1 ); + aList.push_back( MSG_PANEL_ITEM( _( "Graphic Layer" ), msg, BROWN ) ); + + // Display item rotation + // The full rotation is Image rotation + m_lyrRotation + // but m_lyrRotation is specific to this object + // so we display only this parameter + msg.Printf( wxT( "%f" ), m_lyrRotation ); + aList.push_back( MSG_PANEL_ITEM( _( "Rotation" ), msg, BLUE ) ); + + // Display item polarity (item specific) + msg = m_LayerNegative ? _("Clear") : _("Dark"); + aList.push_back( MSG_PANEL_ITEM( _( "Polarity" ), msg, BLUE ) ); + + // Display mirroring (item specific) + msg.Printf( wxT( "A:%s B:%s" ), + m_mirrorA ? _("Yes") : _("No"), + m_mirrorB ? _("Yes") : _("No")); + aList.push_back( MSG_PANEL_ITEM( _( "Mirror" ), msg, DARKRED ) ); + + // Display AB axis swap (item specific) + msg = m_swapAxis ? wxT( "A=Y B=X" ) : wxT( "A=X B=Y" ); + aList.push_back( MSG_PANEL_ITEM( _( "AB axis" ), msg, DARKRED ) ); +} + + +bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const +{ + // calculate aRefPos in XY gerber axis: + wxPoint ref_pos = GetXYPosition( aRefPos ); + + // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items) + int radius = std::min( m_Size.x, m_Size.y ) >> 1; + + if( m_Flashed ) + return HitTestPoints( m_Start, ref_pos, radius ); + else + return TestSegmentHit( ref_pos, m_Start, m_End, radius ); +} + + +bool GERBER_DRAW_ITEM::HitTest( const EDA_RECT& aRefArea ) const +{ + wxPoint pos = GetABPosition( m_Start ); + + if( aRefArea.Contains( pos ) ) + return true; + + pos = GetABPosition( m_End ); + + if( aRefArea.Contains( pos ) ) + return true; + + return false; +} + + +#if defined(DEBUG) + +void GERBER_DRAW_ITEM::Show( int nestLevel, std::ostream& os ) const +{ + NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << + + " shape=\"" << m_Shape << '"' << + " addr=\"" << std::hex << this << std::dec << '"' << + " layer=\"" << m_Layer << '"' << + " size=\"" << m_Size << '"' << + " flags=\"" << m_Flags << '"' << + " status=\"" << GetStatus() << '"' << + "<start" << m_Start << "/>" << + "<end" << m_End << "/>"; + + os << "</" << GetClass().Lower().mb_str() << ">\n"; +} + +#endif diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h new file mode 100644 index 0000000..49e3340 --- /dev/null +++ b/gerbview/class_gerber_draw_item.h @@ -0,0 +1,309 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 <Jean-Pierre Charras> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file class_gerber_draw_item.h + */ + +#ifndef CLASS_GERBER_DRAW_ITEM_H +#define CLASS_GERBER_DRAW_ITEM_H + +#include <base_struct.h> +#include <dlist.h> +#include <layers_id_colors_and_visibility.h> +#include <gr_basic.h> + +class GERBER_IMAGE; +class GBR_LAYOUT; +class D_CODE; +class MSG_PANEL_ITEM; + + +/* Shapes id for basic shapes ( .m_Shape member ) */ +enum Gbr_Basic_Shapes { + GBR_SEGMENT = 0, // usual segment : line with rounded ends + GBR_ARC, // Arcs (with rounded ends) + GBR_CIRCLE, // ring + GBR_POLYGON, // polygonal shape + GBR_SPOT_CIRCLE, // flashed shape: round shape (can have hole) + GBR_SPOT_RECT, // flashed shape: rectangular shape can have hole) + GBR_SPOT_OVAL, // flashed shape: oval shape + GBR_SPOT_POLY, // flashed shape: regular polygon, 3 to 12 edges + GBR_SPOT_MACRO, // complex shape described by a macro + GBR_LAST // last value for this list +}; + +/***/ + +class GERBER_DRAW_ITEM : public EDA_ITEM +{ + // make SetNext() and SetBack() private so that they may not be called from anywhere. + // list management is done on GERBER_DRAW_ITEMs using DLIST<GERBER_DRAW_ITEM> only. +private: + void SetNext( EDA_ITEM* aNext ) { Pnext = aNext; } + void SetBack( EDA_ITEM* aBack ) { Pback = aBack; } + + +public: + bool m_UnitsMetric; /* store here the gerber units (inch/mm). Used + * only to calculate aperture macros shapes sizes */ + int m_Shape; // Shape and type of this gerber item + wxPoint m_Start; // Line or arc start point or position of the shape + // for flashed items + wxPoint m_End; // Line or arc end point + wxPoint m_ArcCentre; // for arcs only: Centre of arc + std::vector <wxPoint> m_PolyCorners; // list of corners for polygons (G36 to G37 coordinates) + // or for complex shapes which are converted to polygon + wxSize m_Size; // Flashed shapes: size of the shape + // Lines : m_Size.x = m_Size.y = line width + bool m_Flashed; // True for flashed items + int m_DCode; // DCode used to draw this item. + // 0 for items that do not use DCodes (polygons) + // or when unknown and normal values are 10 to 999 + // values 0 to 9 can be used for special purposes + GERBER_IMAGE* m_imageParams; /* main GERBER info for this item + * Note: some params stored in this class are common + * to the whole gerber file (i.e) the whole graphic + * layer and some can change when reaging the file, + * so they are stored inside this item there is no + * redundancy for these parameters + */ +private: + int m_Layer; + + // These values are used to draw this item, according to gerber layers parameters + // Because they can change inside a gerber image, they are stored here + // for each item + bool m_LayerNegative; // true = item in negative Layer + bool m_swapAxis; // false if A = X, B = Y; true if A =Y, B = Y + bool m_mirrorA; // true: mirror / axe A + bool m_mirrorB; // true: mirror / axe B + wxRealPoint m_drawScale; // A and B scaling factor + wxPoint m_layerOffset; // Offset for A and B axis, from OF parameter + double m_lyrRotation; // Fine rotation, from OR parameter, in degrees + +public: + GERBER_DRAW_ITEM( GBR_LAYOUT* aParent, GERBER_IMAGE* aGerberparams ); + GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ); + ~GERBER_DRAW_ITEM(); + + /** + * Function Copy + * will copy this object + * the corresponding type. + * @return - GERBER_DRAW_ITEM* + */ + GERBER_DRAW_ITEM* Copy() const; + + GERBER_DRAW_ITEM* Next() const { return static_cast<GERBER_DRAW_ITEM*>( Pnext ); } + GERBER_DRAW_ITEM* Back() const { return static_cast<GERBER_DRAW_ITEM*>( Pback ); } + + /** + * Function GetLayer + * returns the layer this item is on. + */ + int GetLayer() const { return m_Layer; } + + /** + * Function SetLayer + * sets the layer this item is on. + * @param aLayer The layer number. + * is virtual because some items (in fact: class DIMENSION) + * have a slightly different initialization + */ + void SetLayer( int aLayer ) { m_Layer = aLayer; } + + bool GetLayerPolarity() + { + return m_LayerNegative; + } + + /** + * Function HasNegativeItems + * @return true if this item or at least one shape (when using aperture macros + * must be drawn in background color + * used to optimize screen refresh (when no items are in background color + * refresh can be faster) + */ + bool HasNegativeItems(); + + /** + * Function SetLayerParameters + * Initialize parameters from Image and Layer parameters + * found in the gerber file: + * m_UnitsMetric, + * m_MirrorA, m_MirrorB, + * m_DrawScale, m_DrawOffset + */ + void SetLayerParameters(); + + void SetLayerPolarity( bool aNegative) + { + m_LayerNegative = aNegative; + } + + /** + * Function MoveAB + * move this object. + * @param aMoveVector - the move vector for this object. + */ + void MoveAB( const wxPoint& aMoveVector ); + + /** + * Function MoveXY + * move this object. + * @param aMoveVector - the move vector for this object, in XY gerber axis. + */ + void MoveXY( const wxPoint& aMoveVector ); + + /** + * Function GetPosition + * returns the position of this object. + * @return const wxPoint& - The position of this object. + * This function exists mainly to satisfy the virtual GetPosition() in parent class + */ + const wxPoint& GetPosition() const { return m_Start; } + void SetPosition( const wxPoint& aPos ) { m_Start = aPos; } + + /** + * Function GetABPosition + * returns the image position of aPosition for this object. + * Image position is the value of aPosition, modified by image parameters: + * offsets, axis selection, scale, rotation + * @param aXYPosition = position in X,Y gerber axis + * @return const wxPoint - The given position in plotter A,B axis. + */ + wxPoint GetABPosition( const wxPoint& aXYPosition ) const; + + /** + * Function GetXYPosition + * returns the image position of aPosition for this object. + * Image position is the value of aPosition, modified by image parameters: + * offsets, axis selection, scale, rotation + * @param aABPosition = position in A,B plotter axis + * @return const wxPoint - The given position in X,Y axis. + */ + wxPoint GetXYPosition( const wxPoint& aABPosition ) const; + + /** + * Function GetDcodeDescr + * returns the GetDcodeDescr of this object, or NULL. + * @return D_CODE* - a pointer to the DCode description (for flashed items). + */ + D_CODE* GetDcodeDescr(); + + const EDA_RECT GetBoundingBox() const; // Virtual + + /* Display on screen: */ + void Draw( EDA_DRAW_PANEL* aPanel, + wxDC* aDC, + GR_DRAWMODE aDrawMode, + const wxPoint&aOffset ); + + /** + * Function ConvertSegmentToPolygon + * convert a line to an equivalent polygon. + * Useful when a line is plotted using a rectangular pen. + * In this case, the usual segment plot function cannot be used + */ + void ConvertSegmentToPolygon(); + + /** + * Function DrawGbrPoly + * a helper function used to draw the polygon stored in m_PolyCorners + */ + void DrawGbrPoly( EDA_RECT* aClipBox, + wxDC* aDC, EDA_COLOR_T aColor, + const wxPoint& aOffset, bool aFilledShape ); + + /* divers */ + int Shape() const { return m_Shape; } + + void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ); + + wxString ShowGBRShape(); + + /** + * Function HitTest + * tests if the given wxPoint is within the bounds of this object. + * @param aRefPos a wxPoint to test + * @return bool - true if a hit, else false + */ + bool HitTest( const wxPoint& aRefPos ) const; + + /** + * Function HitTest (overloaded) + * tests if the given wxRect intersect this object. + * For now, an ending point must be inside this rect. + * @param aRefArea a wxPoint to test + * @return bool - true if a hit, else false + */ + bool HitTest( const EDA_RECT& aRefArea ) const; + + /** + * Function GetClass + * returns the class name. + * @return wxString + */ + wxString GetClass() const + { + return wxT( "GERBER_DRAW_ITEM" ); + } + + /** + * Function Save. + * currently: no nothing, but must be defined to meet requirements + * of the basic class + */ + bool Save( FILE* aFile ) const; + + /** + * Function UnLink + * detaches this object from its owner. + */ + void UnLink() + { + DLIST<GERBER_DRAW_ITEM>* list = (DLIST<GERBER_DRAW_ITEM>*) GetList(); + wxASSERT( list ); + + if( list ) + list->Remove( this ); + } + + /** + * Function DeleteStructure + * deletes this object after UnLink()ing it from its owner. + */ + void DeleteStructure() + { + UnLink(); + delete this; + } +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const; // override +#endif + +}; + +#endif /* CLASS_GERBER_DRAW_ITEM_H */ diff --git a/gerbview/class_gerbview_layer_widget.cpp b/gerbview/class_gerbview_layer_widget.cpp new file mode 100644 index 0000000..f2108ac --- /dev/null +++ b/gerbview/class_gerbview_layer_widget.cpp @@ -0,0 +1,338 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2010 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +/** + * @file class_gerbview_layer_widget.cpp + * @brief GerbView layers manager. + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <pcbstruct.h> +#include <macros.h> +#include <class_gbr_layer_box_selector.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_GERBER.h> +#include <layer_widget.h> +#include <class_gerbview_layer_widget.h> +#include <class_X2_gerber_attributes.h> + + +/* + * Class GERBER_LAYER_WIDGET + * is here to implement the abtract functions of LAYER_WIDGET so they + * may be tied into the GERBVIEW_FRAME's data and so we can add a popup + * menu which is specific to Pcbnew's needs. + */ + + +GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner, + int aPointSize ) : + LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), + myframe( aParent ) +{ + m_alwaysShowActiveLayer = false; + + ReFillRender(); + + // Update default tabs labels for GerbView + SetLayersManagerTabsText( ); + + //-----<Popup menu>------------------------------------------------- + // handle the popup menu over the layer window. + m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN, + wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + + // since Popupmenu() calls this->ProcessEvent() we must call this->Connect() + // and not m_LayerScrolledWindow->Connect() + Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END, + wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this ); + + // install the right click handler into each control at end of ReFill() + // using installRightLayerClickHandler +} + +/** + * Function SetLayersManagerTabsText + * Update the layer manager tabs labels + * Useful when changing Language or to set labels to a non default value + */ +void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( ) +{ + m_notebook->SetPageText(0, _("Layer") ); + m_notebook->SetPageText(1, _("Render") ); +} + +/** + * Function ReFillRender + * Rebuild Render for instance after the config is read + */ +void GERBER_LAYER_WIDGET::ReFillRender() +{ + ClearRenderRows(); + + // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color + // is changed before appending to the LAYER_WIDGET. This is an automatic variable + // not a static variable, change the color & state after copying from code to renderRows + // on the stack. + LAYER_WIDGET::ROW renderRows[3] = { + +#define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width + + // text id color tooltip checked + RR( _( "Grid" ), GERBER_GRID_VISIBLE, WHITE, _( "Show the (x,y) grid dots" ) ), + RR( _( "DCodes" ), DCODES_VISIBLE, WHITE, _( "Show DCodes identification" ) ), + RR( _( "Neg. Obj." ), NEGATIVE_OBJECTS_VISIBLE, DARKGRAY, + _( "Show negative objects in this color" ) ), + }; + + for( unsigned row=0; row<DIM(renderRows); ++row ) + { + if( renderRows[row].color != -1 ) // does this row show a color? + { + renderRows[row].color = myframe->GetVisibleElementColor( + (GERBER_VISIBLE_ID)renderRows[row].id ); + } + renderRows[row].state = myframe->IsElementVisible( + (GERBER_VISIBLE_ID)renderRows[row].id ); + } + + AppendRenderRows( renderRows, DIM(renderRows) ); +} + +void GERBER_LAYER_WIDGET::installRightLayerClickHandler() +{ + int rowCount = GetLayerRowCount(); + + for( int row=0; row<rowCount; ++row ) + { + for( int col=0; col<LYR_COLUMN_COUNT; ++col ) + { + wxWindow* w = getLayerComp( row, col ); + + w->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( + GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + } + } +} + + +void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) +{ + wxMenu menu; + + // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt) + menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_LAYERS, + _("Show All Layers") ) ); + + menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS_BUT_ACTIVE, + _( "Hide All Layers But Active" ) ) ); + + menu.Append( new wxMenuItem( &menu, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE, + _( "Always Hide All Layers But Active" ) ) ); + + menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS, + _( "Hide All Layers" ) ) ); + + menu.AppendSeparator(); + menu.Append( new wxMenuItem( &menu, ID_SORT_GBR_LAYERS, + _( "Sort Layers if X2 Mode" ) ) ); + PopupMenu( &menu ); + + passOnFocus(); +} + +void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) +{ + int rowCount; + int menuId = event.GetId(); + bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false; + long visibleLayers = 0; + bool force_active_layer_visible; + + m_alwaysShowActiveLayer = ( menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE ); + force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE || + menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE ); + + switch( menuId ) + { + case ID_SHOW_ALL_LAYERS: + case ID_SHOW_NO_LAYERS: + case ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE: + case ID_SHOW_NO_LAYERS_BUT_ACTIVE: + rowCount = GetLayerRowCount(); + for( int row=0; row < rowCount; ++row ) + { + wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB ); + int layer = getDecodedId( cb->GetId() ); + bool loc_visible = visible; + + if( force_active_layer_visible && (layer == myframe->getActiveLayer() ) ) + loc_visible = true; + + cb->SetValue( loc_visible ); + + if( loc_visible ) + visibleLayers |= 1 << row; + else + visibleLayers &= ~( 1 << row ); + } + + myframe->SetVisibleLayers( visibleLayers ); + myframe->GetCanvas()->Refresh(); + break; + + case ID_SORT_GBR_LAYERS: + g_GERBER_List.SortImagesByZOrder( myframe->GetItemsList() ); + myframe->ReFillLayerWidget(); + myframe->syncLayerBox(); + myframe->GetCanvas()->Refresh(); + break; + } +} + +bool GERBER_LAYER_WIDGET::OnLayerSelected() +{ + if( !m_alwaysShowActiveLayer ) + return false; + + // postprocess after active layer selection + // ensure active layer visible + wxCommandEvent event; + event.SetId( ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE ); + onPopupSelection( event ); + return true; +} + + +void GERBER_LAYER_WIDGET::ReFill() +{ + Freeze(); + + ClearLayerRows(); + + for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) + { + wxString msg = g_GERBER_List.GetDisplayName( layer ); + + AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, + myframe->GetLayerColor( layer ), wxEmptyString, true ) ); + } + + Thaw(); + + installRightLayerClickHandler(); +} + +//-----<LAYER_WIDGET callbacks>------------------------------------------- + +void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, EDA_COLOR_T aColor ) +{ + myframe->SetLayerColor( aLayer, aColor ); + myframe->m_SelLayerBox->ResyncBitmapOnly(); + myframe->GetCanvas()->Refresh(); +} + +bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer ) +{ + // the layer change from the GERBER_LAYER_WIDGET can be denied by returning + // false from this function. + int layer = myframe->getActiveLayer( ); + myframe->setActiveLayer( aLayer, false ); + myframe->syncLayerBox(); + + if( layer != myframe->getActiveLayer( ) ) + { + if( ! OnLayerSelected() ) + myframe->GetCanvas()->Refresh(); + } + + return true; +} + +void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal ) +{ + long visibleLayers = myframe->GetVisibleLayers(); + + if( isVisible ) + visibleLayers |= 1 << aLayer; + else + visibleLayers &= ~( 1 << aLayer ); + + myframe->SetVisibleLayers( visibleLayers ); + + if( isFinal ) + myframe->GetCanvas()->Refresh(); +} + +void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, EDA_COLOR_T aColor ) +{ + myframe->SetVisibleElementColor( (GERBER_VISIBLE_ID)aId, aColor ); + myframe->GetCanvas()->Refresh(); +} + +void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) +{ + myframe->SetElementVisibility( (GERBER_VISIBLE_ID)aId, isEnabled ); + myframe->GetCanvas()->Refresh(); +} + +//-----</LAYER_WIDGET callbacks>------------------------------------------ + +/* + * Virtual Function useAlternateBitmap + * return true if bitmaps shown in Render layer list + * must be alternate bitmaps, or false to use "normal" bitmaps + */ +bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow) +{ + return g_GERBER_List.IsUsed( aRow ); +} + +/* + * Update the layer manager icons (layers only) + * Useful when loading a file or clearing a layer because they change + */ +void GERBER_LAYER_WIDGET::UpdateLayerIcons() +{ + int row_count = GetLayerRowCount(); + for( int row = 0; row < row_count ; row++ ) + { + wxStaticBitmap* bm = (wxStaticBitmap*) getLayerComp( row, COLUMN_ICON_ACTIVE ); + if( bm == NULL) + continue; + + if( row == m_CurrentRow ) + bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap : + *m_RightArrowBitmap ); + else + bm->SetBitmap( useAlternateBitmap(row) ? *m_BlankAlternateBitmap : *m_BlankBitmap ); + } +} diff --git a/gerbview/class_gerbview_layer_widget.h b/gerbview/class_gerbview_layer_widget.h new file mode 100644 index 0000000..d7dfc78 --- /dev/null +++ b/gerbview/class_gerbview_layer_widget.h @@ -0,0 +1,134 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +/************************************************************/ +/* class_gerber_layer_widget.h : header for the layers manager */ +/************************************************************/ + +#ifndef _CLASS_GERBER_LAYER_WIDGET_H_ +#define _CLASS_GERBER_LAYER_WIDGET_H_ + +#include <layer_widget.h> + +// popup menu ids. in layer manager +enum LAYER_MANAGER +{ + ID_LAYER_MANAGER_START = wxID_HIGHEST+1, + ID_SHOW_ALL_LAYERS = ID_LAYER_MANAGER_START, + ID_SHOW_NO_LAYERS, + ID_SHOW_NO_LAYERS_BUT_ACTIVE, + ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE, + ID_SORT_GBR_LAYERS, + ID_LAYER_MANAGER_END = ID_SORT_GBR_LAYERS, +}; + +/** + * Class GERBER_LAYER_WIDGET + * is here to implement the abtract functions of LAYER_WIDGET so they + * may be tied into the GERBVIEW_FRAME's data and so we can add a popup + * menu which is specific to Pcbnew's needs. + */ +class GERBER_LAYER_WIDGET : public LAYER_WIDGET +{ + GERBVIEW_FRAME* myframe; + bool m_alwaysShowActiveLayer; // If true: Only shows the current active layer + // even if it is changed + + + /** + * Function OnRightDownLayers + * puts up a popup menu for the layer panel. + */ + void onRightDownLayers( wxMouseEvent& event ); + + void onPopupSelection( wxCommandEvent& event ); + + /// this is for the popup menu, the right click handler has to be installed + /// on every child control within the layer panel. + void installRightLayerClickHandler(); + + /** + * Virtual Function useAlternateBitmap + * @return true if bitmaps shown in Render layer list + * are alternate bitmaps, or false if they are "normal" bitmaps + */ + virtual bool useAlternateBitmap(int aRow); + +public: + + /** + * Constructor + * @param aParent : the parent frame + * @param aFocusOwner : the window that has the keyboard focus. + * @param aPointSize is the font point size to use within the widget. This + * effectively sets the overal size of the widget via the row height and bitmap + * button sizes. + */ + GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize = 10 ); + + void ReFill(); + + /** + * Function ReFillRender + * Rebuild Render for instance after the config is read + */ + void ReFillRender(); + + //-----<implement LAYER_WIDGET abstract callback functions>----------- + void OnLayerColorChange( int aLayer, EDA_COLOR_T aColor ); + bool OnLayerSelect( int aLayer ); + void OnLayerVisible( int aLayer, bool isVisible, bool isFinal ); + void OnRenderColorChange( int aId, EDA_COLOR_T aColor ); + void OnRenderEnable( int aId, bool isEnabled ); + /** + * Function SetLayersManagerTabsText + * Update the layer manager tabs labels + * Useful when changing Language or to set labels to a non default value + */ + void SetLayersManagerTabsText( ); + //-----</implement LAYER_WIDGET abstract callback functions>---------- + + /** + * Function OnLayerSelected + * ensure the active layer is visible, and other layers not visible + * when m_alwaysShowActiveLayer is true + * Otherwise do nothing. + * @return true m_alwaysShowActiveLayer is true and the canvas is refreshed, + * and false if do nothing + */ + bool OnLayerSelected(); // postprocess after an active layer selection + // ensure active layer visible if + // m_alwaysShowActiveCopperLayer is true; + + /** + * Function UpdateLayerIcons + * Update the layer manager icons (layers only) + * Useful when loading a file or clearing a layer because they change + */ + void UpdateLayerIcons(); +}; + +#endif // _CLASS_GERBER_LAYER_WIDGET_H_ diff --git a/gerbview/controle.cpp b/gerbview/controle.cpp new file mode 100644 index 0000000..ace281c --- /dev/null +++ b/gerbview/controle.cpp @@ -0,0 +1,62 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 <Jean-Pierre Charras> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview/controle.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <gerbview.h> +#include <gerbview_frame.h> + + +bool GERBVIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey ) +{ + bool eventHandled = true; + + // Filter out the 'fake' mouse motion after a keyboard movement + if( !aHotKey && m_movingCursorWithKeyboard ) + { + m_movingCursorWithKeyboard = false; + return false; + } + + wxPoint pos = aPosition; + wxPoint oldpos = GetCrossHairPosition(); + GeneralControlKeyMovement( aHotKey, &pos, true ); + + SetCrossHairPosition( pos ); + RefreshCrossHair( oldpos, aPosition, aDC ); + + if( aHotKey ) + { + eventHandled = OnHotKey( aDC, aHotKey, aPosition ); + } + + UpdateStatusBar(); + + return eventHandled; +} diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp new file mode 100644 index 0000000..8063b81 --- /dev/null +++ b/gerbview/dcode.cpp @@ -0,0 +1,531 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2009 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file dcode.cpp + * @brief D_CODE class implementation + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <macros.h> +#include <trigo.h> +#include <gr_basic.h> +#include <base_units.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> + +#define DEFAULT_SIZE 100 + +/* Format Gerber: NOTES: + * Tools and D_CODES + * tool number (identification of shapes) + * 1 to 999 + * + * D_CODES: + * D01 ... D9 = command codes: + * D01 = activating light (pen down) while moving + * D02 = light extinction (pen up) while moving + * D03 = Flash + * D04 to D09 = non used + * D10 ... D999 = Identification Tool (Shape id) + * + * For tools defining a shape): + * DCode min = D10 + * DCode max = 999 + */ + + +/***************/ +/* Class DCODE */ +/***************/ + + +D_CODE::D_CODE( int num_dcode ) +{ + m_Num_Dcode = num_dcode; + Clear_D_CODE_Data(); +} + + +D_CODE::~D_CODE() +{ +} + + +void D_CODE::Clear_D_CODE_Data() +{ + m_Size.x = DEFAULT_SIZE; + m_Size.y = DEFAULT_SIZE; + m_Shape = APT_CIRCLE; + m_Drill.x = m_Drill.y = 0; + m_DrillShape = APT_DEF_NO_HOLE; + m_InUse = false; + m_Defined = false; + m_Macro = NULL; + m_Rotation = 0.0; + m_EdgesCount = 0; + m_PolyCorners.clear(); +} + + +const wxChar* D_CODE::ShowApertureType( APERTURE_T aType ) +{ + const wxChar* ret; + + switch( aType ) + { + case APT_CIRCLE: + ret = wxT( "Round" ); break; + + case APT_RECT: + ret = wxT( "Rect" ); break; + + case APT_OVAL: + ret = wxT( "Oval" ); break; + + case APT_POLYGON: + ret = wxT( "Poly" ); break; + + case APT_MACRO: + ret = wxT( "Macro" ); break; + + default: + ret = wxT( "???" ); break; + } + + return ret; +} + +int D_CODE::GetShapeDim( GERBER_DRAW_ITEM* aParent ) +{ + int dim = -1; + switch( m_Shape ) + { + case APT_CIRCLE: + dim = m_Size.x; + break; + + case APT_RECT: + case APT_OVAL: + dim = std::min( m_Size.x, m_Size.y ); + break; + + case APT_POLYGON: + dim = std::min( m_Size.x, m_Size.y ); + break; + + case APT_MACRO: + if( m_Macro ) + dim = m_Macro->GetShapeDim( aParent ); + break; + + default: + break; + } + + return dim; +} + + +void GERBVIEW_FRAME::CopyDCodesSizeToItems() +{ + static D_CODE dummy( 999 ); //Used if D_CODE not found in list + + GERBER_DRAW_ITEM* gerb_item = GetItemsList(); + for( ; gerb_item; gerb_item = gerb_item->Next() ) + { + D_CODE* dcode = gerb_item->GetDcodeDescr(); + wxASSERT( dcode ); + if( dcode == NULL ) + dcode = &dummy; + + dcode->m_InUse = true; + + gerb_item->m_Size = dcode->m_Size; + + if( // Line Item + (gerb_item->m_Shape == GBR_SEGMENT ) /* rectilinear segment */ + || (gerb_item->m_Shape == GBR_ARC ) /* segment arc (rounded tips) */ + || (gerb_item->m_Shape == GBR_CIRCLE ) /* segment in a circle (ring) */ + ) + { + } + else // Spots ( Flashed Items ) + { + switch( dcode->m_Shape ) + { + case APT_CIRCLE: /* spot round */ + gerb_item->m_Shape = GBR_SPOT_CIRCLE; + break; + + case APT_OVAL: /* spot oval*/ + gerb_item->m_Shape = GBR_SPOT_OVAL; + break; + + case APT_RECT: /* spot rect*/ + gerb_item->m_Shape = GBR_SPOT_RECT; + break; + + case APT_POLYGON: + gerb_item->m_Shape = GBR_SPOT_POLY; + break; + + case APT_MACRO: /* spot defined by a macro */ + gerb_item->m_Shape = GBR_SPOT_MACRO; + break; + + default: + wxMessageBox( wxT( "GERBVIEW_FRAME::CopyDCodesSizeToItems() error" ) ); + break; + } + } + } +} + + +void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, wxDC* aDC, EDA_COLOR_T aColor, + EDA_COLOR_T aAltColor, + wxPoint aShapePos, bool aFilledShape ) +{ + int radius; + + switch( m_Shape ) + { + case APT_MACRO: + GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aAltColor, + aShapePos, aFilledShape); + break; + + case APT_CIRCLE: + radius = m_Size.x >> 1; + if( !aFilledShape ) + GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor ); + else + if( m_DrillShape == APT_DEF_NO_HOLE ) + { + GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), + radius, aColor ); + } + else if( APT_DEF_ROUND_HOLE == 1 ) // round hole in shape + { + int width = (m_Size.x - m_Drill.x ) / 2; + GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), + radius - (width / 2), width, aColor ); + } + else // rectangular hole + { + if( m_PolyCorners.size() == 0 ) + ConvertShapeToPolygon(); + + DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); + } + break; + + case APT_RECT: + { + wxPoint start; + start.x = aShapePos.x - m_Size.x / 2; + start.y = aShapePos.y - m_Size.y / 2; + wxPoint end = start + m_Size; + start = aParent->GetABPosition( start ); + end = aParent->GetABPosition( end ); + + if( !aFilledShape ) + { + GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor ); + } + else if( m_DrillShape == APT_DEF_NO_HOLE ) + { + GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor ); + } + else + { + if( m_PolyCorners.size() == 0 ) + ConvertShapeToPolygon(); + + DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); + } + } + break; + + case APT_OVAL: + { + wxPoint start = aShapePos; + wxPoint end = aShapePos; + + if( m_Size.x > m_Size.y ) // horizontal oval + { + int delta = (m_Size.x - m_Size.y) / 2; + start.x -= delta; + end.x += delta; + radius = m_Size.y; + } + else // horizontal oval + { + int delta = (m_Size.y - m_Size.x) / 2; + start.y -= delta; + end.y += delta; + radius = m_Size.x; + } + + start = aParent->GetABPosition( start ); + end = aParent->GetABPosition( end ); + + if( !aFilledShape ) + { + GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); + } + else if( m_DrillShape == APT_DEF_NO_HOLE ) + { + GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); + } + else + { + if( m_PolyCorners.size() == 0 ) + ConvertShapeToPolygon(); + + DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); + } + } + break; + + case APT_POLYGON: + if( m_PolyCorners.size() == 0 ) + ConvertShapeToPolygon(); + + DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); + break; + } +} + + +void D_CODE::DrawFlashedPolygon( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, wxDC* aDC, + EDA_COLOR_T aColor, bool aFilled, + const wxPoint& aPosition ) +{ + if( m_PolyCorners.size() == 0 ) + return; + + std::vector<wxPoint> points; + points = m_PolyCorners; + + for( unsigned ii = 0; ii < points.size(); ii++ ) + { + points[ii] += aPosition; + points[ii] = aParent->GetABPosition( points[ii] ); + } + + GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilled, aColor, aColor ); +} + + +#define SEGS_CNT 32 // number of segments to approximate a circle + + +// A helper function for D_CODE::ConvertShapeToPolygon(). Add a hole to a polygon +static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, + APERTURE_DEF_HOLETYPE aHoleShape, + wxSize aSize, + wxPoint aAnchorPos ); + + +void D_CODE::ConvertShapeToPolygon() +{ + wxPoint initialpos; + wxPoint currpos; + + m_PolyCorners.clear(); + + switch( m_Shape ) + { + case APT_CIRCLE: // creates only a circle with rectangular hole + currpos.x = m_Size.x >> 1; + initialpos = currpos; + + for( unsigned ii = 0; ii <= SEGS_CNT; ii++ ) + { + currpos = initialpos; + RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); + m_PolyCorners.push_back( currpos ); + } + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + break; + + case APT_RECT: + currpos.x = m_Size.x / 2; + currpos.y = m_Size.y / 2; + initialpos = currpos; + m_PolyCorners.push_back( currpos ); + currpos.x -= m_Size.x; + m_PolyCorners.push_back( currpos ); + currpos.y -= m_Size.y; + m_PolyCorners.push_back( currpos ); + currpos.x += m_Size.x; + m_PolyCorners.push_back( currpos ); + currpos.y += m_Size.y; + m_PolyCorners.push_back( currpos ); // close polygon + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + break; + + case APT_OVAL: + { + int delta, radius; + + // we create an horizontal oval shape. then rotate if needed + if( m_Size.x > m_Size.y ) // horizontal oval + { + delta = (m_Size.x - m_Size.y) / 2; + radius = m_Size.y / 2; + } + else // vertical oval + { + delta = (m_Size.y - m_Size.x) / 2; + radius = m_Size.x / 2; + } + + currpos.y = radius; + initialpos = currpos; + m_PolyCorners.push_back( currpos ); + + // build the right arc of the shape + unsigned ii = 0; + + for( ; ii <= SEGS_CNT / 2; ii++ ) + { + currpos = initialpos; + RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); + currpos.x += delta; + m_PolyCorners.push_back( currpos ); + } + + // build the left arc of the shape + for( ii = SEGS_CNT / 2; ii <= SEGS_CNT; ii++ ) + { + currpos = initialpos; + RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); + currpos.x -= delta; + m_PolyCorners.push_back( currpos ); + } + + m_PolyCorners.push_back( initialpos ); // close outline + + if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon. + { + for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) + RotatePoint( &m_PolyCorners[jj], 900 ); + } + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + } + break; + + case APT_POLYGON: + currpos.x = m_Size.x >> 1; // first point is on X axis + initialpos = currpos; + + // rs274x said: m_EdgesCount = 3 ... 12 + if( m_EdgesCount < 3 ) + m_EdgesCount = 3; + + if( m_EdgesCount > 12 ) + m_EdgesCount = 12; + + for( int ii = 0; ii <= m_EdgesCount; ii++ ) + { + currpos = initialpos; + RotatePoint( &currpos, ii * 3600.0 / m_EdgesCount ); + m_PolyCorners.push_back( currpos ); + } + + addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + + if( m_Rotation ) // vertical oval, rotate polygon. + { + int angle = KiROUND( m_Rotation * 10 ); + + for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) + { + RotatePoint( &m_PolyCorners[jj], -angle ); + } + } + + break; + + case APT_MACRO: + + // TODO + break; + } +} + + +// The helper function for D_CODE::ConvertShapeToPolygon(). +// Add a hole to a polygon +static void addHoleToPolygon( std::vector<wxPoint>& aBuffer, + APERTURE_DEF_HOLETYPE aHoleShape, + wxSize aSize, + wxPoint aAnchorPos ) +{ + wxPoint currpos; + + if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole + { + for( int ii = 0; ii <= SEGS_CNT; ii++ ) + { + currpos.x = 0; + currpos.y = aSize.x / 2; // aSize.x / 2 is the radius of the hole + RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); + aBuffer.push_back( currpos ); + } + + aBuffer.push_back( aAnchorPos ); // link to outline + } + + if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole + { + currpos.x = aSize.x / 2; + currpos.y = aSize.y / 2; + aBuffer.push_back( currpos ); // link to hole and begin hole + currpos.x -= aSize.x; + aBuffer.push_back( currpos ); + currpos.y -= aSize.y; + aBuffer.push_back( currpos ); + currpos.x += aSize.x; + aBuffer.push_back( currpos ); + currpos.y += aSize.y; + aBuffer.push_back( currpos ); // close hole + aBuffer.push_back( aAnchorPos ); // link to outline + } +} diff --git a/gerbview/dcode.h b/gerbview/dcode.h new file mode 100644 index 0000000..ebc36c1 --- /dev/null +++ b/gerbview/dcode.h @@ -0,0 +1,218 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr> + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file dcode.h + */ + +#ifndef _DCODE_H_ +#define _DCODE_H_ + +#include <vector> + +#include <base_struct.h> + + +class GERBER_DRAW_ITEM; + + +/** + * Enum APERTURE_T + * is the set of all gerber aperture types allowed, according to page 16 of + * http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf + */ +enum APERTURE_T { + APT_CIRCLE = 'C', // Flashed shape: Circle with or without hole + APT_RECT = 'R', // Flashed shape: Rectangle with or without hole + APT_OVAL = '0', // Flashed shape: Oval with or without hole + APT_POLYGON = 'P', // Flashed shape: Regular polygon (3 to 12 edges) + // with or without hole. Can be rotated + APT_MACRO = 'M' // Complex shape given by a macro definition (see AM_PRIMITIVE_ID) +}; + +// In aperture definition, round, oval and rectangular flashed shapes +// can have a hole (round or rectangular) +// this option is stored in .m_DrillShape D_CODE member +enum APERTURE_DEF_HOLETYPE { + APT_DEF_NO_HOLE = 0, + APT_DEF_ROUND_HOLE, + APT_DEF_RECT_HOLE +}; + +/* define min and max values for D Codes values. + * note: values >= 0 and > FIRST_DCODE can be used for special purposes + */ +#define FIRST_DCODE 10 +#define LAST_DCODE 999 +#define TOOLS_MAX_COUNT (LAST_DCODE + 1) + +struct APERTURE_MACRO; + + +/** + * Class D_CODE + * holds a gerber DCODE definition. + */ +class D_CODE +{ +private: + APERTURE_MACRO* m_Macro; ///< no ownership, points to + // GERBER.m_aperture_macros element + /** + * parameters used only when this D_CODE holds a reference to an aperture + * macro, and these parameters would customize the macro. + */ + std::vector<double> m_am_params; + + std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw APT_POLYGON shape and some other + * complex shapes which are converted to polygon + * (shapes with hole ) + */ + +public: + wxSize m_Size; /* Horizontal and vertical dimensions. */ + APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */ + int m_Num_Dcode; /* D code ( >= 10 ) */ + wxSize m_Drill; /* dimension of the hole (if any) */ + APERTURE_DEF_HOLETYPE m_DrillShape; /* shape of the hole (0 = no hole, round = 1, rect = 2) */ + double m_Rotation; /* shape rotation in degrees */ + int m_EdgesCount; /* in aperture definition Polygon only: number of edges for the polygon */ + bool m_InUse; /* false if not used */ + bool m_Defined; /* false if not defined */ + wxString m_SpecialDescr; + +public: + D_CODE( int num_dcode ); + ~D_CODE(); + void Clear_D_CODE_Data(); + + /** + * AppendParam() + * Add a parameter to the D_CODE parameter list. + * used to customize the corresponding aperture macro + */ + void AppendParam( double aValue ) + { + m_am_params.push_back( aValue ); + } + + /** + * GetParamCount() + * Returns the number of parameters stored in parameter list. + */ + unsigned GetParamCount() const + { + return m_am_params.size(); + } + + /** + * GetParam() + * Returns a parameter stored in parameter list. + * @param aIdx = index of parameter + */ + double GetParam( unsigned aIdx ) const + { + wxASSERT( aIdx <= m_am_params.size() ); + if( aIdx <= m_am_params.size() ) + return m_am_params[aIdx - 1]; + else + return 0; + } + + + void SetMacro( APERTURE_MACRO* aMacro ) + { + m_Macro = aMacro; + } + + + APERTURE_MACRO* GetMacro() const { return m_Macro; } + + /** + * Function ShowApertureType + * returns a character string telling what type of aperture type \a aType is. + * @param aType The aperture type to show. + */ + static const wxChar* ShowApertureType( APERTURE_T aType ); + + /** + * Function DrawFlashedShape + * Draw the dcode shape for flashed items. + * When an item is flashed, the DCode shape is the shape of the item + * @param aParent = the GERBER_DRAW_ITEM being drawn + * @param aClipBox = DC clip box (NULL is no clip) + * @param aDC = device context + * @param aColor = the normal color to use + * @param aAltColor = the color used to draw with "reverse" exposure mode (used in + * aperture macros only) + * @param aShapePos = the actual shape position + * @param aFilledShape = true to draw in filled mode, false to draw in sketch mode + */ + void DrawFlashedShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, + wxDC* aDC, EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, + wxPoint aShapePos, bool aFilledShape ); + + /** + * Function DrawFlashedPolygon + * a helper function used to draw the polygon stored ion m_PolyCorners + * Draw some Apertures shapes when they are defined as filled polygons. + * APT_POLYGON is always a polygon, but some complex shapes are also converted to + * polygons (shapes with holes, some rotated shapes) + * @param aParent = the GERBER_DRAW_ITEM being drawn + * @param aClipBox = DC clip box (NULL is no clip) + * @param aDC = device context + * @param aColor = the normal color to use + * @param aFilled = true to draw in filled mode, false to draw in sketch mode + * @param aPosition = the actual shape position + */ + void DrawFlashedPolygon( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, wxDC* aDC, EDA_COLOR_T aColor, + bool aFilled, const wxPoint& aPosition ); + + /** + * Function ConvertShapeToPolygon + * convert a shape to an equivalent polygon. + * Arcs and circles are approximated by segments + * Useful when a shape is not a graphic primitive (shape with hole, + * rotated shape ... ) and cannot be easily drawn. + */ + void ConvertShapeToPolygon(); + + /** + * Function GetShapeDim + * calculates a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of some shapes, + * one cannot calculate the "size" of a shape (only a bounding box) + * but here, the "dimension" of the shape is the diameter of the primitive + * or for lines the width of the line if the shape is a line + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return a dimension, or -1 if no dim to calculate + */ + int GetShapeDim( GERBER_DRAW_ITEM* aParent ); +}; + + +#endif // ifndef _DCODE_H_ diff --git a/gerbview/dialogs/dialog_layers_select_to_pcb_base.cpp b/gerbview/dialogs/dialog_layers_select_to_pcb_base.cpp new file mode 100644 index 0000000..068d992 --- /dev/null +++ b/gerbview/dialogs/dialog_layers_select_to_pcb_base.cpp @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_layers_select_to_pcb_base.h" + +/////////////////////////////////////////////////////////////////////////// + +BEGIN_EVENT_TABLE( LAYERS_MAP_DIALOG_BASE, DIALOG_SHIM ) + EVT_COMBOBOX( ID_M_COMBOCOPPERLAYERSCOUNT, LAYERS_MAP_DIALOG_BASE::_wxFB_OnBrdLayersCountSelection ) + EVT_BUTTON( ID_STORE_CHOICE, LAYERS_MAP_DIALOG_BASE::_wxFB_OnStoreSetup ) + EVT_BUTTON( ID_GET_PREVIOUS_CHOICE, LAYERS_MAP_DIALOG_BASE::_wxFB_OnGetSetup ) + EVT_BUTTON( ID_RESET_CHOICE, LAYERS_MAP_DIALOG_BASE::_wxFB_OnResetClick ) + EVT_BUTTON( wxID_CANCEL, LAYERS_MAP_DIALOG_BASE::_wxFB_OnCancelClick ) + EVT_BUTTON( wxID_OK, LAYERS_MAP_DIALOG_BASE::_wxFB_OnOkClick ) +END_EVENT_TABLE() + +LAYERS_MAP_DIALOG_BASE::LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* sbUpperSizer; + sbUpperSizer = new wxBoxSizer( wxHORIZONTAL ); + + sbSizerLayersTable = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Layers selection:") ), wxHORIZONTAL ); + + m_flexLeftColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 ); + m_flexLeftColumnBoxSizer->AddGrowableCol( 0 ); + m_flexLeftColumnBoxSizer->AddGrowableCol( 1 ); + m_flexLeftColumnBoxSizer->AddGrowableCol( 2 ); + m_flexLeftColumnBoxSizer->AddGrowableCol( 3 ); + m_flexLeftColumnBoxSizer->SetFlexibleDirection( wxBOTH ); + m_flexLeftColumnBoxSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + + sbSizerLayersTable->Add( m_flexLeftColumnBoxSizer, 1, wxEXPAND, 5 ); + + m_staticlineSep = new wxStaticLine( this, ID_M_STATICLINESEP, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + sbSizerLayersTable->Add( m_staticlineSep, 0, wxEXPAND | wxALL, 5 ); + + + sbUpperSizer->Add( sbSizerLayersTable, 1, wxEXPAND, 5 ); + + wxBoxSizer* bRightSizer; + bRightSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizerLyrCnt; + bSizerLyrCnt = new wxBoxSizer( wxVERTICAL ); + + m_staticTextCopperlayerCount = new wxStaticText( this, ID_M_STATICTEXTCOPPERLAYERCOUNT, _("Copper layers count:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticTextCopperlayerCount->Wrap( -1 ); + bSizerLyrCnt->Add( m_staticTextCopperlayerCount, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_comboCopperLayersCount = new wxComboBox( this, ID_M_COMBOCOPPERLAYERSCOUNT, _("2 Layers"), wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); + m_comboCopperLayersCount->Append( _("2 Layers") ); + m_comboCopperLayersCount->Append( _("4 Layers") ); + m_comboCopperLayersCount->Append( _("6 Layers") ); + m_comboCopperLayersCount->Append( _("8 Layers") ); + m_comboCopperLayersCount->Append( _("10 Layers") ); + m_comboCopperLayersCount->Append( _("12 Layers") ); + m_comboCopperLayersCount->Append( _("14 Layers") ); + m_comboCopperLayersCount->Append( _("16 Layers") ); + bSizerLyrCnt->Add( m_comboCopperLayersCount, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + bRightSizer->Add( bSizerLyrCnt, 0, wxEXPAND, 5 ); + + + bRightSizer->Add( 5, 15, 1, wxEXPAND, 5 ); + + wxBoxSizer* bSizerButtons; + bSizerButtons = new wxBoxSizer( wxVERTICAL ); + + m_buttonStore = new wxButton( this, ID_STORE_CHOICE, _("Store Choice"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerButtons->Add( m_buttonStore, 0, wxALL|wxEXPAND, 5 ); + + m_buttonRetrieve = new wxButton( this, ID_GET_PREVIOUS_CHOICE, _("Get Stored Choice"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerButtons->Add( m_buttonRetrieve, 0, wxALL|wxEXPAND, 5 ); + + m_buttonReset = new wxButton( this, ID_RESET_CHOICE, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerButtons->Add( m_buttonReset, 0, wxALL|wxEXPAND, 5 ); + + + bRightSizer->Add( bSizerButtons, 0, wxEXPAND, 5 ); + + + sbUpperSizer->Add( bRightSizer, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + bSizerMain->Add( sbUpperSizer, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bSizerMain->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_sdbSizerButtons = new wxStdDialogButtonSizer(); + m_sdbSizerButtonsOK = new wxButton( this, wxID_OK ); + m_sdbSizerButtons->AddButton( m_sdbSizerButtonsOK ); + m_sdbSizerButtonsCancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizerButtons->AddButton( m_sdbSizerButtonsCancel ); + m_sdbSizerButtons->Realize(); + + bSizerMain->Add( m_sdbSizerButtons, 0, wxALIGN_RIGHT|wxALL, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + + this->Centre( wxBOTH ); +} + +LAYERS_MAP_DIALOG_BASE::~LAYERS_MAP_DIALOG_BASE() +{ +} diff --git a/gerbview/dialogs/dialog_layers_select_to_pcb_base.fbp b/gerbview/dialogs/dialog_layers_select_to_pcb_base.fbp new file mode 100644 index 0000000..2969fb1 --- /dev/null +++ b/gerbview/dialogs/dialog_layers_select_to_pcb_base.fbp @@ -0,0 +1,809 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="11" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">table</property> + <property name="file">dialog_layers_select_to_pcb_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">dialog_layers_select_to_pcb_base</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="use_enum">1</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center">wxBOTH</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">ID_LAYERS_MAP_DIALOG_BASE</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">LAYERS_MAP_DIALOG_BASE</property> + <property name="pos"></property> + <property name="size">400,286</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Layer selection:</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerMain</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">sbUpperSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Layers selection:</property> + <property name="minimum_size"></property> + <property name="name">sbSizerLayersTable</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">protected</property> + <event name="OnUpdateUI"></event> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxFlexGridSizer" expanded="1"> + <property name="cols">4</property> + <property name="flexible_direction">wxBOTH</property> + <property name="growablecols">0,1,2,3</property> + <property name="growablerows"></property> + <property name="hgap">0</property> + <property name="minimum_size"></property> + <property name="name">m_flexLeftColumnBoxSizer</property> + <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property> + <property name="permission">protected</property> + <property name="rows">16</property> + <property name="vgap">0</property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND | wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_M_STATICLINESEP</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticlineSep</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_VERTICAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bRightSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerLyrCnt</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxTOP|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_M_STATICTEXTCOPPERLAYERCOUNT</property> + <property name="label">Copper layers count:</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticTextCopperlayerCount</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxComboBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"2 Layers" "4 Layers" "6 Layers" "8 Layers" "10 Layers" "12 Layers" "14 Layers" "16 Layers"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_M_COMBOCOPPERLAYERSCOUNT</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_comboCopperLayersCount</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">-1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value">2 Layers</property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCombobox">OnBrdLayersCountSelection</event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnText"></event> + <event name="OnTextEnter"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="spacer" expanded="1"> + <property name="height">15</property> + <property name="permission">protected</property> + <property name="width">5</property> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bSizerButtons</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_STORE_CHOICE</property> + <property name="label">Store Choice</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonStore</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnStoreSetup</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_GET_PREVIOUS_CHOICE</property> + <property name="label">Get Stored Choice</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonRetrieve</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnGetSetup</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">ID_RESET_CHOICE</property> + <property name="label">Reset</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonReset</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnResetClick</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticline1</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_HORIZONTAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_RIGHT|wxALL</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">0</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizerButtons</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick"></event> + <event name="OnCancelButtonClick">OnCancelClick</event> + <event name="OnContextHelpButtonClick"></event> + <event name="OnHelpButtonClick"></event> + <event name="OnNoButtonClick"></event> + <event name="OnOKButtonClick">OnOkClick</event> + <event name="OnSaveButtonClick"></event> + <event name="OnYesButtonClick"></event> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/gerbview/dialogs/dialog_layers_select_to_pcb_base.h b/gerbview/dialogs/dialog_layers_select_to_pcb_base.h new file mode 100644 index 0000000..c5cfba6 --- /dev/null +++ b/gerbview/dialogs/dialog_layers_select_to_pcb_base.h @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__ +#define __DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +#include "dialog_shim.h" +#include <wx/sizer.h> +#include <wx/gdicmn.h> +#include <wx/statline.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/string.h> +#include <wx/statbox.h> +#include <wx/stattext.h> +#include <wx/combobox.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class LAYERS_MAP_DIALOG_BASE +/////////////////////////////////////////////////////////////////////////////// +class LAYERS_MAP_DIALOG_BASE : public DIALOG_SHIM +{ + DECLARE_EVENT_TABLE() + private: + + // Private event handlers + void _wxFB_OnBrdLayersCountSelection( wxCommandEvent& event ){ OnBrdLayersCountSelection( event ); } + void _wxFB_OnStoreSetup( wxCommandEvent& event ){ OnStoreSetup( event ); } + void _wxFB_OnGetSetup( wxCommandEvent& event ){ OnGetSetup( event ); } + void _wxFB_OnResetClick( wxCommandEvent& event ){ OnResetClick( event ); } + void _wxFB_OnCancelClick( wxCommandEvent& event ){ OnCancelClick( event ); } + void _wxFB_OnOkClick( wxCommandEvent& event ){ OnOkClick( event ); } + + + protected: + enum + { + ID_LAYERS_MAP_DIALOG_BASE = 1000, + ID_M_STATICLINESEP, + ID_M_STATICTEXTCOPPERLAYERCOUNT, + ID_M_COMBOCOPPERLAYERSCOUNT, + ID_STORE_CHOICE, + ID_GET_PREVIOUS_CHOICE, + ID_RESET_CHOICE + }; + + wxStaticBoxSizer* sbSizerLayersTable; + wxFlexGridSizer* m_flexLeftColumnBoxSizer; + wxStaticLine* m_staticlineSep; + wxStaticText* m_staticTextCopperlayerCount; + wxComboBox* m_comboCopperLayersCount; + wxButton* m_buttonStore; + wxButton* m_buttonRetrieve; + wxButton* m_buttonReset; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizerButtons; + wxButton* m_sdbSizerButtonsOK; + wxButton* m_sdbSizerButtonsCancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnBrdLayersCountSelection( wxCommandEvent& event ) { event.Skip(); } + virtual void OnStoreSetup( wxCommandEvent& event ) { event.Skip(); } + virtual void OnGetSetup( wxCommandEvent& event ) { event.Skip(); } + virtual void OnResetClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + LAYERS_MAP_DIALOG_BASE( wxWindow* parent, wxWindowID id = ID_LAYERS_MAP_DIALOG_BASE, const wxString& title = _("Layer selection:"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 400,286 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~LAYERS_MAP_DIALOG_BASE(); + +}; + +#endif //__DIALOG_LAYERS_SELECT_TO_PCB_BASE_H__ diff --git a/gerbview/dialogs/dialog_print_using_printer.cpp b/gerbview/dialogs/dialog_print_using_printer.cpp new file mode 100644 index 0000000..9141f3f --- /dev/null +++ b/gerbview/dialogs/dialog_print_using_printer.cpp @@ -0,0 +1,404 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +// Set this to 1 if you want to test PostScript printing under MSW. +#define wxTEST_POSTSCRIPT_IN_MSW 1 + +#include <fctsys.h> + +#include <kiface_i.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> + +#include <dialog_print_using_printer_base.h> +#include <printout_controler.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_GERBER.h> +#include <pcbplot.h> + +static double s_ScaleList[] = +{ 0, 0.5, 0.7, 0.999, 1.0, 1.4, 2.0, 3.0, 4.0 }; + +// Define min et max reasonnable values for print scale +#define MIN_SCALE 0.01 +#define MAX_SCALE 100.0 + +// static print data and page setup data, to remember settings during the session +static wxPrintData* s_printData; +static wxPageSetupDialogData* s_pageSetupData = (wxPageSetupDialogData*) NULL; + +// Variables locales +static PRINT_PARAMETERS s_Parameters; + + +/* Dialog to print schematic. Class derived from DIALOG_PRINT_USING_PRINTER_BASE + * created by wxFormBuilder + */ +class DIALOG_PRINT_USING_PRINTER : public DIALOG_PRINT_USING_PRINTER_BASE +{ +private: + GERBVIEW_FRAME* m_Parent; + wxConfigBase* m_Config; + wxCheckBox* m_BoxSelectLayer[32]; + +public: + DIALOG_PRINT_USING_PRINTER( GERBVIEW_FRAME* parent ); + ~DIALOG_PRINT_USING_PRINTER() {}; + +private: + void OnCloseWindow( wxCloseEvent& event ); + void OnInitDialog( wxInitDialogEvent& event ); + void OnPageSetup( wxCommandEvent& event ); + void OnPrintPreview( wxCommandEvent& event ); + void OnPrintButtonClick( wxCommandEvent& event ); + void OnScaleSelectionClick( wxCommandEvent& event ); + + void OnButtonCancelClick( wxCommandEvent& event ) { Close(); } + void SetPrintParameters(); + void InitValues(); + +public: + bool IsMirrored() { return m_Print_Mirror->IsChecked(); } + bool PrintUsingSinglePage() { return true; } + int SetLayerSetFromListSelection(); + // Prepare print parameters. return true if OK, + // false if there is an issue (mainly no printable layers) + bool PreparePrintPrms(); +}; + + +/*******************************************************/ +void GERBVIEW_FRAME::ToPrinter( wxCommandEvent& event ) +/*******************************************************/ + +/* Virtual function: + * Display the print dialog + */ +{ + if( s_printData == NULL ) // First print + s_printData = new wxPrintData(); + + if( !s_printData->Ok() ) + { + DisplayError( this, _( "Error Init Printer info" ) ); + return; + } + + s_printData->SetQuality( wxPRINT_QUALITY_HIGH ); + s_printData->SetOrientation( GetPageSettings().IsPortrait() ? + wxPORTRAIT : wxLANDSCAPE ); + + DIALOG_PRINT_USING_PRINTER* frame = new DIALOG_PRINT_USING_PRINTER( this ); + + frame->ShowModal(); + frame->Destroy(); +} + + +/*************************************************************************************/ +DIALOG_PRINT_USING_PRINTER::DIALOG_PRINT_USING_PRINTER( GERBVIEW_FRAME* parent ) : + DIALOG_PRINT_USING_PRINTER_BASE( parent ) +/*************************************************************************************/ +{ + m_Parent = parent; + m_Config = Kiface().KifaceSettings(); + + InitValues( ); + GetSizer()->SetSizeHints( this ); + +#ifdef __WXMAC__ + /* Problems with modal on wx-2.9 - Anyway preview is standard for OSX */ + m_buttonPreview->Hide(); +#endif + + GetSizer()->Fit( this ); +} + + +/************************************************************************/ +void DIALOG_PRINT_USING_PRINTER::InitValues( ) +/************************************************************************/ +{ + SetFocus(); + wxString msg; + + if( s_pageSetupData == NULL ) + { + s_pageSetupData = new wxPageSetupDialogData; + // Set initial page margins. + // Margins are already set in Gerbview, so we can use 0 + s_pageSetupData->SetMarginTopLeft( wxPoint( 0, 0 ) ); + s_pageSetupData->SetMarginBottomRight( wxPoint( 0, 0 ) ); + } + + s_Parameters.m_PageSetupData = s_pageSetupData; + + // Create layer list + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + msg = _( "Layer" ); + msg << wxT( " " ) << ii + 1; + + wxStaticBoxSizer* boxSizer = ( ii < 16 ) ? m_leftLayersBoxSizer + : m_rightLayersBoxSizer; + + m_BoxSelectLayer[ii] = new wxCheckBox( boxSizer->GetStaticBox(), + wxID_ANY, msg ); + boxSizer->Add( m_BoxSelectLayer[ii], wxGROW | wxLEFT | wxRIGHT | wxTOP ); + + if( g_GERBER_List.GetGbrImage( ii ) == NULL ) + // Nothing loaded on this draw layer + m_BoxSelectLayer[ii]->Enable( false ); + } + + // Read the scale adjust option + int scale_idx = 4; // default selected scale = ScaleList[4] = 1.000 + + if( m_Config ) + { + m_Config->Read( OPTKEY_PRINT_X_FINESCALE_ADJ, &s_Parameters.m_XScaleAdjust ); + m_Config->Read( OPTKEY_PRINT_Y_FINESCALE_ADJ, &s_Parameters.m_YScaleAdjust ); + m_Config->Read( OPTKEY_PRINT_SCALE, &scale_idx ); + m_Config->Read( OPTKEY_PRINT_PAGE_FRAME, &s_Parameters.m_Print_Sheet_Ref, 1 ); + m_Config->Read( OPTKEY_PRINT_MONOCHROME_MODE, &s_Parameters.m_Print_Black_and_White, 1 ); + + // Test for a reasonnable scale value. Set to 1 if problem + if( s_Parameters.m_XScaleAdjust < MIN_SCALE || + s_Parameters.m_YScaleAdjust < MIN_SCALE || + s_Parameters.m_XScaleAdjust > MAX_SCALE || + s_Parameters.m_YScaleAdjust > MAX_SCALE ) + s_Parameters.m_XScaleAdjust = s_Parameters.m_YScaleAdjust = 1.0; + + for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) + { + wxString layerKey; + bool option; + + layerKey.Printf( OPTKEY_LAYERBASE, layer ); + m_Config->Read( layerKey, &option, false ); + m_BoxSelectLayer[layer]->SetValue( option ); + } + } + + m_ScaleOption->SetSelection( scale_idx ); + scale_idx = m_ScaleOption->GetSelection(); + s_Parameters.m_PrintScale = s_ScaleList[scale_idx]; + m_Print_Mirror->SetValue( s_Parameters.m_PrintMirror ); + + + if( s_Parameters.m_Print_Black_and_White ) + m_ModeColorOption->SetSelection( 1 ); + else + m_ModeColorOption->SetSelection( 0 ); + + s_Parameters.m_PenDefaultSize = 0; + + // Create scale adjust option + msg.Printf( wxT( "%f" ), s_Parameters.m_XScaleAdjust ); + m_FineAdjustXscaleOpt->SetValue( msg ); + msg.Printf( wxT( "%f" ), s_Parameters.m_YScaleAdjust ); + m_FineAdjustYscaleOpt->SetValue( msg ); + + bool enable = (s_Parameters.m_PrintScale == 1.0); + + m_FineAdjustXscaleOpt->Enable(enable); + m_FineAdjustYscaleOpt->Enable(enable); +} + + +int DIALOG_PRINT_USING_PRINTER::SetLayerSetFromListSelection() +{ + int page_count = 0; + std::bitset <GERBER_DRAWLAYERS_COUNT> layerMask; + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + if( m_BoxSelectLayer[ii]->IsChecked() && m_BoxSelectLayer[ii]->IsEnabled() ) + { + page_count++; + layerMask[ii] = true; + } + else + layerMask[ii] = false; + } + + m_Parent->GetGerberLayout()->SetPrintableLayers( layerMask ); + s_Parameters.m_PageCount = page_count; + + return page_count; +} + + +void DIALOG_PRINT_USING_PRINTER::OnCloseWindow( wxCloseEvent& event ) +{ + SetPrintParameters(); + + if( m_Config ) + { + m_Config->Write( OPTKEY_PRINT_X_FINESCALE_ADJ, s_Parameters.m_XScaleAdjust ); + m_Config->Write( OPTKEY_PRINT_Y_FINESCALE_ADJ, s_Parameters.m_YScaleAdjust ); + m_Config->Write( OPTKEY_PRINT_SCALE, m_ScaleOption->GetSelection() ); + m_Config->Write( OPTKEY_PRINT_PAGE_FRAME, s_Parameters.m_Print_Sheet_Ref); + m_Config->Write( OPTKEY_PRINT_MONOCHROME_MODE, s_Parameters.m_Print_Black_and_White); + wxString layerKey; + for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) + { + layerKey.Printf( OPTKEY_LAYERBASE, layer ); + m_Config->Write( layerKey, m_BoxSelectLayer[layer]->IsChecked() ); + } + } + + EndModal( 0 ); +} + + +void DIALOG_PRINT_USING_PRINTER::SetPrintParameters() +{ + s_Parameters.m_PrintMirror = m_Print_Mirror->GetValue(); + s_Parameters.m_Print_Black_and_White = + m_ModeColorOption->GetSelection() != 0; + + // Due to negative objects in gerber objects, always use one page per image, + // because these objects create artefact when they are printed on an existing image. + s_Parameters.m_OptionPrintPage = false; + + SetLayerSetFromListSelection(); + + int idx = m_ScaleOption->GetSelection(); + s_Parameters.m_PrintScale = s_ScaleList[idx]; + + if( m_FineAdjustXscaleOpt ) + { + if( s_Parameters.m_XScaleAdjust > MAX_SCALE || + s_Parameters.m_YScaleAdjust > MAX_SCALE ) + DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very large value" ) ); + m_FineAdjustXscaleOpt->GetValue().ToDouble( &s_Parameters.m_XScaleAdjust ); + } + if( m_FineAdjustYscaleOpt ) + { + // Test for a reasonnable scale value + if( s_Parameters.m_XScaleAdjust < MIN_SCALE || + s_Parameters.m_YScaleAdjust < MIN_SCALE ) + DisplayInfoMessage( NULL, _( "Warning: Scale option set to a very small value" ) ); + m_FineAdjustYscaleOpt->GetValue().ToDouble( &s_Parameters.m_YScaleAdjust ); + } +} + +void DIALOG_PRINT_USING_PRINTER::OnScaleSelectionClick( wxCommandEvent& event ) +{ + double scale = s_ScaleList[m_ScaleOption->GetSelection()]; + bool enable = (scale == 1.0); + if( m_FineAdjustXscaleOpt ) + m_FineAdjustXscaleOpt->Enable(enable); + if( m_FineAdjustYscaleOpt ) + m_FineAdjustYscaleOpt->Enable(enable); +} + +// Open a dialog box for printer setup (printer options, page size ...) +void DIALOG_PRINT_USING_PRINTER::OnPageSetup( wxCommandEvent& event ) +{ + *s_pageSetupData = *s_printData; + + wxPageSetupDialog pageSetupDialog(this, s_pageSetupData); + pageSetupDialog.ShowModal(); + + (*s_printData) = pageSetupDialog.GetPageSetupDialogData().GetPrintData(); + (*s_pageSetupData) = pageSetupDialog.GetPageSetupDialogData(); +} + +bool DIALOG_PRINT_USING_PRINTER::PreparePrintPrms() +{ + SetPrintParameters(); + + // If no layer selected, we have no plot. prompt user if it happens + // because he could think there is a bug in Pcbnew: + if( m_Parent->GetGerberLayout()->GetPrintableLayers().none() ) + { + DisplayError( this, _( "No layer selected" ) ); + return false; + } + + return true; +} + +// Open and display a previewer frame for printing +void DIALOG_PRINT_USING_PRINTER::OnPrintPreview( wxCommandEvent& event ) +{ + if( !PreparePrintPrms() ) + return; + + // Pass two printout objects: for preview, and possible printing. + wxString title = _( "Print Preview" ); + wxPrintPreview* preview = + new wxPrintPreview( new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_Parent, title ), + new BOARD_PRINTOUT_CONTROLLER( s_Parameters, m_Parent, title ), + s_printData ); + + if( preview == NULL ) + { + DisplayError( this, wxT( "OnPrintPreview() problem" ) ); + return; + } + + + // Uses the parent position and size. + // @todo uses last position and size ans store them when exit in m_Config + wxPoint WPos = m_Parent->GetPosition(); + wxSize WSize = m_Parent->GetSize(); + + wxPreviewFrame* frame = new wxPreviewFrame( preview, this, title, WPos, WSize ); + frame->SetMinSize( wxSize( 550, 350 ) ); + + frame->Initialize(); + + frame->Raise(); // Needed on Ubuntu/Unity to display the frame + frame->Show( true ); +} + + +void DIALOG_PRINT_USING_PRINTER::OnPrintButtonClick( wxCommandEvent& event ) +{ + if( !PreparePrintPrms() ) + return; + + wxPrintDialogData printDialogData( *s_printData ); + + wxPrinter printer( &printDialogData ); + wxString title = _( "Print" ); + BOARD_PRINTOUT_CONTROLLER printout( s_Parameters, m_Parent, title ); + + if( !printer.Print( this, &printout, true ) ) + { + if( wxPrinter::GetLastError() == wxPRINTER_ERROR ) + DisplayError( this, _( "There was a problem printing" ) ); + return; + } + else + { + *s_printData = printer.GetPrintDialogData().GetPrintData(); + } +} + diff --git a/gerbview/dialogs/dialog_print_using_printer_base.cpp b/gerbview/dialogs/dialog_print_using_printer_base.cpp new file mode 100644 index 0000000..1202588 --- /dev/null +++ b/gerbview/dialogs/dialog_print_using_printer_base.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 9 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_print_using_printer_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_PRINT_USING_PRINTER_BASE::DIALOG_PRINT_USING_PRINTER_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize ); + + wxBoxSizer* bMainSizer; + bMainSizer = new wxBoxSizer( wxHORIZONTAL ); + + wxStaticBoxSizer* sbLayersSizer; + sbLayersSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Layers:") ), wxVERTICAL ); + + wxBoxSizer* bleftSizer; + bleftSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_leftLayersBoxSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Layers:") ), wxVERTICAL ); + + + bleftSizer->Add( m_leftLayersBoxSizer, 1, wxALL, 5 ); + + m_rightLayersBoxSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Layers:") ), wxVERTICAL ); + + + bleftSizer->Add( m_rightLayersBoxSizer, 1, wxALL, 5 ); + + + sbLayersSizer->Add( bleftSizer, 1, wxEXPAND, 5 ); + + + bMainSizer->Add( sbLayersSizer, 1, wxEXPAND, 5 ); + + wxBoxSizer* bmiddleLeftSizer; + bmiddleLeftSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_ScaleOptionChoices[] = { _("fit in page"), _("Scale 0.5"), _("Scale 0.7"), _("Approx. Scale 1"), _("Accurate Scale 1"), _("Scale 1.4"), _("Scale 2"), _("Scale 3"), _("Scale 4") }; + int m_ScaleOptionNChoices = sizeof( m_ScaleOptionChoices ) / sizeof( wxString ); + m_ScaleOption = new wxRadioBox( this, wxID_ANY, _("Approx. Scale:"), wxDefaultPosition, wxDefaultSize, m_ScaleOptionNChoices, m_ScaleOptionChoices, 1, wxRA_SPECIFY_COLS ); + m_ScaleOption->SetSelection( 3 ); + bmiddleLeftSizer->Add( m_ScaleOption, 0, wxALL, 5 ); + + m_FineAdjustXscaleTitle = new wxStaticText( this, wxID_ANY, _("X Scale Adjust"), wxDefaultPosition, wxDefaultSize, 0 ); + m_FineAdjustXscaleTitle->Wrap( -1 ); + bmiddleLeftSizer->Add( m_FineAdjustXscaleTitle, 0, wxRIGHT|wxLEFT, 5 ); + + m_FineAdjustXscaleOpt = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_FineAdjustXscaleOpt->SetMaxLength( 0 ); + m_FineAdjustXscaleOpt->SetToolTip( _("Set X scale adjust for exact scale plotting") ); + + bmiddleLeftSizer->Add( m_FineAdjustXscaleOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + m_FineAdjustYscaleTitle = new wxStaticText( this, wxID_ANY, _("Y Scale Adjust"), wxDefaultPosition, wxDefaultSize, 0 ); + m_FineAdjustYscaleTitle->Wrap( -1 ); + bmiddleLeftSizer->Add( m_FineAdjustYscaleTitle, 0, wxRIGHT|wxLEFT, 5 ); + + m_FineAdjustYscaleOpt = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_FineAdjustYscaleOpt->SetMaxLength( 0 ); + m_FineAdjustYscaleOpt->SetToolTip( _("Set Y scale adjust for exact scale plotting") ); + + bmiddleLeftSizer->Add( m_FineAdjustYscaleOpt, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND, 5 ); + + + bMainSizer->Add( bmiddleLeftSizer, 0, wxEXPAND, 5 ); + + wxBoxSizer* bmiddleRightSizer; + bmiddleRightSizer = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbOptionsSizer; + sbOptionsSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options:") ), wxVERTICAL ); + + m_Print_Mirror = new wxCheckBox( this, wxID_ANY, _("Mirror"), wxDefaultPosition, wxDefaultSize, 0 ); + sbOptionsSizer->Add( m_Print_Mirror, 0, wxALL, 5 ); + + + bmiddleRightSizer->Add( sbOptionsSizer, 0, wxEXPAND|wxALL, 5 ); + + wxString m_ModeColorOptionChoices[] = { _("Color"), _("Black and white") }; + int m_ModeColorOptionNChoices = sizeof( m_ModeColorOptionChoices ) / sizeof( wxString ); + m_ModeColorOption = new wxRadioBox( this, wxID_PRINT_MODE, _("Print Mode"), wxDefaultPosition, wxDefaultSize, m_ModeColorOptionNChoices, m_ModeColorOptionChoices, 1, wxRA_SPECIFY_COLS ); + m_ModeColorOption->SetSelection( 0 ); + m_ModeColorOption->SetToolTip( _("Choose if you want to print sheets in color, or force the black and white mode.") ); + + bmiddleRightSizer->Add( m_ModeColorOption, 0, wxALL|wxEXPAND, 5 ); + + + bMainSizer->Add( bmiddleRightSizer, 0, wxEXPAND, 5 ); + + wxBoxSizer* b_buttonsSizer; + b_buttonsSizer = new wxBoxSizer( wxVERTICAL ); + + m_buttonOption = new wxButton( this, wxID_PRINT_OPTIONS, _("Page Options"), wxDefaultPosition, wxDefaultSize, 0 ); + b_buttonsSizer->Add( m_buttonOption, 0, wxALL|wxEXPAND, 5 ); + + m_buttonPreview = new wxButton( this, wxID_PREVIEW, _("Preview"), wxDefaultPosition, wxDefaultSize, 0 ); + b_buttonsSizer->Add( m_buttonPreview, 0, wxALL|wxEXPAND, 5 ); + + m_buttonPrint = new wxButton( this, wxID_PRINT_ALL, _("Print"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonPrint->SetDefault(); + b_buttonsSizer->Add( m_buttonPrint, 0, wxALL|wxEXPAND, 5 ); + + m_buttonQuit = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); + b_buttonsSizer->Add( m_buttonQuit, 0, wxALL|wxEXPAND, 5 ); + + + bMainSizer->Add( b_buttonsSizer, 0, wxALIGN_CENTER_VERTICAL, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnCloseWindow ) ); + m_ScaleOption->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnScaleSelectionClick ), NULL, this ); + m_buttonOption->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPageSetup ), NULL, this ); + m_buttonPreview->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPrintPreview ), NULL, this ); + m_buttonPrint->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPrintButtonClick ), NULL, this ); + m_buttonQuit->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnButtonCancelClick ), NULL, this ); +} + +DIALOG_PRINT_USING_PRINTER_BASE::~DIALOG_PRINT_USING_PRINTER_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnCloseWindow ) ); + m_ScaleOption->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnScaleSelectionClick ), NULL, this ); + m_buttonOption->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPageSetup ), NULL, this ); + m_buttonPreview->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPrintPreview ), NULL, this ); + m_buttonPrint->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnPrintButtonClick ), NULL, this ); + m_buttonQuit->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PRINT_USING_PRINTER_BASE::OnButtonCancelClick ), NULL, this ); + +} diff --git a/gerbview/dialogs/dialog_print_using_printer_base.fbp b/gerbview/dialogs/dialog_print_using_printer_base.fbp new file mode 100644 index 0000000..184cdb8 --- /dev/null +++ b/gerbview/dialogs/dialog_print_using_printer_base.fbp @@ -0,0 +1,1167 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="13" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">dialog_print_using_printer_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">DialogPrint_base</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_lua_events">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="ui_table">UI</property> + <property name="use_enum">1</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size">-1,-1</property> + <property name="name">DIALOG_PRINT_USING_PRINTER_BASE</property> + <property name="pos"></property> + <property name="size">551,314</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Print</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose">OnCloseWindow</event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bMainSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Layers:</property> + <property name="minimum_size"></property> + <property name="name">sbLayersSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <event name="OnUpdateUI"></event> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bleftSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">1</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Layers:</property> + <property name="minimum_size"></property> + <property name="name">m_leftLayersBoxSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">protected</property> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">1</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Layers:</property> + <property name="minimum_size"></property> + <property name="name">m_rightLayersBoxSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">protected</property> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bmiddleLeftSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"fit in page" "Scale 0.5" "Scale 0.7" "Approx. Scale 1" "Accurate Scale 1" "Scale 1.4" "Scale 2" "Scale 3" "Scale 4"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Approx. Scale:</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_ScaleOption</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">3</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox">OnScaleSelectionClick</event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">X Scale Adjust</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_FineAdjustXscaleTitle</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxTextCtrl" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="maxlength">0</property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_FineAdjustXscaleOpt</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip">Set X scale adjust for exact scale plotting</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnText"></event> + <event name="OnTextEnter"></event> + <event name="OnTextMaxLen"></event> + <event name="OnTextURL"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticText" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Y Scale Adjust</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_FineAdjustYscaleTitle</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <property name="wrap">-1</property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxTextCtrl" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="maxlength">0</property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_FineAdjustYscaleOpt</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip">Set Y scale adjust for exact scale plotting</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="value"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnText"></event> + <event name="OnTextEnter"></event> + <event name="OnTextMaxLen"></event> + <event name="OnTextURL"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bmiddleRightSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxALL</property> + <property name="proportion">0</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Options:</property> + <property name="minimum_size"></property> + <property name="name">sbOptionsSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <event name="OnUpdateUI"></event> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Mirror</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_Print_Mirror</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Color" "Black and white"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_PRINT_MODE</property> + <property name="label">Print Mode</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_ModeColorOption</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">0</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip">Choose if you want to print sheets in color, or force the black and white mode.</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALIGN_CENTER_VERTICAL</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">b_buttonsSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_PRINT_OPTIONS</property> + <property name="label">Page Options</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonOption</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnPageSetup</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_PREVIEW</property> + <property name="label">Preview</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonPreview</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnPrintPreview</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_PRINT_ALL</property> + <property name="label">Print</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonPrint</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnPrintButtonClick</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_CANCEL</property> + <property name="label">Close</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_buttonQuit</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnButtonClick">OnButtonCancelClick</event> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/gerbview/dialogs/dialog_print_using_printer_base.h b/gerbview/dialogs/dialog_print_using_printer_base.h new file mode 100644 index 0000000..f99650c --- /dev/null +++ b/gerbview/dialogs/dialog_print_using_printer_base.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Mar 9 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_PRINT_USING_PRINTER_BASE_H__ +#define __DIALOG_PRINT_USING_PRINTER_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include <wx/string.h> +#include <wx/sizer.h> +#include <wx/statbox.h> +#include <wx/gdicmn.h> +#include <wx/radiobox.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/stattext.h> +#include <wx/textctrl.h> +#include <wx/checkbox.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_PRINT_USING_PRINTER_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_PRINT_USING_PRINTER_BASE : public DIALOG_SHIM +{ + private: + + protected: + enum + { + wxID_PRINT_MODE = 1000, + wxID_PRINT_OPTIONS, + wxID_PRINT_ALL + }; + + wxStaticBoxSizer* m_leftLayersBoxSizer; + wxStaticBoxSizer* m_rightLayersBoxSizer; + wxRadioBox* m_ScaleOption; + wxStaticText* m_FineAdjustXscaleTitle; + wxTextCtrl* m_FineAdjustXscaleOpt; + wxStaticText* m_FineAdjustYscaleTitle; + wxTextCtrl* m_FineAdjustYscaleOpt; + wxCheckBox* m_Print_Mirror; + wxRadioBox* m_ModeColorOption; + wxButton* m_buttonOption; + wxButton* m_buttonPreview; + wxButton* m_buttonPrint; + wxButton* m_buttonQuit; + + // Virtual event handlers, overide them in your derived class + virtual void OnCloseWindow( wxCloseEvent& event ) { event.Skip(); } + virtual void OnScaleSelectionClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnPageSetup( wxCommandEvent& event ) { event.Skip(); } + virtual void OnPrintPreview( wxCommandEvent& event ) { event.Skip(); } + virtual void OnPrintButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnButtonCancelClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_PRINT_USING_PRINTER_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Print"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 551,314 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_PRINT_USING_PRINTER_BASE(); + +}; + +#endif //__DIALOG_PRINT_USING_PRINTER_BASE_H__ diff --git a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp new file mode 100644 index 0000000..1a847ce --- /dev/null +++ b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp @@ -0,0 +1,277 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file dialog_select_one_pcb_layer.cpp + * @brief Set up a dialog to choose a PCB Layer. + */ + +#include <fctsys.h> +#include <gerbview_frame.h> +#include <select_layers_to_pcb.h> + +#define NB_PCB_LAYERS LAYER_ID_COUNT +#define FIRST_COPPER_LAYER 0 +#define LAST_COPPER_LAYER 31 + +// Exported function +const wxString GetPCBDefaultLayerName( int aLayerId ); + + +enum layer_sel_id { + ID_LAYER_SELECT_TOP = 1800, + ID_LAYER_SELECT_BOTTOM, + ID_LAYER_SELECT +}; + + +class SELECT_LAYER_DIALOG : public wxDialog +{ +private: + wxRadioBox* m_layerList; + std::vector <int> m_layerId; + +public: + // Constructor and destructor + SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, int aDefaultLayer, + int aCopperLayerCount, bool aShowDeselectOption ); + ~SELECT_LAYER_DIALOG() { }; + +private: + void OnLayerSelected( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); + + DECLARE_EVENT_TABLE() +}; + + +BEGIN_EVENT_TABLE( SELECT_LAYER_DIALOG, wxDialog ) + EVT_BUTTON( wxID_OK, SELECT_LAYER_DIALOG::OnLayerSelected ) + EVT_BUTTON( wxID_CANCEL, SELECT_LAYER_DIALOG::OnCancelClick ) + EVT_RADIOBOX( ID_LAYER_SELECT, SELECT_LAYER_DIALOG::OnLayerSelected ) +END_EVENT_TABLE() + + +/** Install the dialog box for layer selection + * @param aDefaultLayer = Preselection (GERBER_DRAWLAYERS_COUNT for "(Deselect)" layer) + * @param aCopperLayerCount = number of copper layers + * @param aShowDeselectOption = display a "(Deselect)" radiobutton (when set to true) + * @return new layer value (GERBER_DRAWLAYERS_COUNT when "(Deselect)" radiobutton selected), + * or -1 if canceled + * + * Providing the option to also display a "(Deselect)" radiobutton makes the + * GerbView's "Export to Pcbnew" command) more "user friendly", + * by permitting any layer to be "deselected" immediately after its + * corresponding radiobutton has been clicked on. (It would otherwise be + * necessary to first cancel the "Select Layer:" dialog box (invoked after a + * different radiobutton is clicked on) prior to then clicking on the "Deselect" + * button provided within the "Layer selection:" dialog box). + */ +int GERBVIEW_FRAME::SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount, + bool aShowDeselectOption ) +{ + SELECT_LAYER_DIALOG* frame = new SELECT_LAYER_DIALOG( this, aDefaultLayer, + aCopperLayerCount, + aShowDeselectOption ); + + int layer = frame->ShowModal(); + frame->Destroy(); + return layer; +} + + +/* + * The "OK" and "Cancel" buttons are positioned (in a horizontal line) + * beneath the "Layer" radiobox, unless that contains only one column of + * radiobuttons, in which case they are positioned (in a vertical line) + * to the right of that radiobox. + */ +SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, + int aDefaultLayer, int aCopperLayerCount, + bool aShowDeselectOption ) : + wxDialog( parent, -1, _( "Select Layer:" ), wxPoint( -1, -1 ), + wxSize( 470, 250 ), + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) +{ + wxButton* button; + int ii; + wxArrayString layerList; + int layerSelect = -1; + + // Build the layer list; first build copper layers list + int layerCount = 0; + + for( ii = FIRST_COPPER_LAYER; ii <= LAST_COPPER_LAYER; ++ii ) + { + if( ii == FIRST_COPPER_LAYER || ii == LAST_COPPER_LAYER || ii < aCopperLayerCount-1 ) + { + layerList.Add( GetPCBDefaultLayerName( ii ) ); + + if( ii == aDefaultLayer ) + layerSelect = layerCount; + + m_layerId.push_back( ii ); + layerCount++; + } + } + + // Build the layer list; build non copper layers list + for( ; ii < NB_PCB_LAYERS; ++ii ) + { + layerList.Add( GetPCBDefaultLayerName( ii ) ); + + if( ii == aDefaultLayer ) + layerSelect = layerCount; + + m_layerId.push_back( ii ); + layerCount++; + } + + // When appropriate, also provide a "(Deselect)" radiobutton + if( aShowDeselectOption ) + { + layerList.Add( _( "Do not export" ) ); + + if( UNSELECTED_LAYER == aDefaultLayer ) + layerSelect = layerCount; + + m_layerId.push_back( UNSELECTED_LAYER ); + layerCount++; + } + + m_layerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ), + wxPoint( -1, -1 ), wxSize( -1, -1 ), + layerList, + (layerCount < 8) ? layerCount : 8, + wxRA_SPECIFY_ROWS ); + + if( layerSelect >= 0 ) + m_layerList->SetSelection( layerSelect ); + + wxBoxSizer* FrameBoxSizer = new wxBoxSizer( wxHORIZONTAL ); + SetSizer( FrameBoxSizer ); + FrameBoxSizer->Add( m_layerList, 0, wxALIGN_TOP | wxALL, 5 ); + wxBoxSizer* ButtonBoxSizer = new wxBoxSizer( wxVERTICAL ); + FrameBoxSizer->Add( ButtonBoxSizer, 0, wxALIGN_BOTTOM | wxALL, 0 ); + + button = new wxButton( this, wxID_OK, _( "OK" ) ); + button->SetDefault(); + ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 ); + + button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); + ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 ); + + GetSizer()->SetSizeHints( this ); + + Center(); +} + + +void SELECT_LAYER_DIALOG::OnLayerSelected( wxCommandEvent& event ) +{ + int ii = m_layerId[m_layerList->GetSelection()]; + + EndModal( ii ); +} + + +void SELECT_LAYER_DIALOG::OnCancelClick( wxCommandEvent& event ) +{ + EndModal( -1 ); +} + +// This function is a duplicate of +// const wxChar* LSET::Name( LAYER_ID aLayerId ) +// However it avoids a dependency to Pcbnew code. +const wxString GetPCBDefaultLayerName( int aLayerId ) +{ + const wxChar* txt; + + // using a switch to explicitly show the mapping more clearly + switch( aLayerId ) + { + case F_Cu: txt = wxT( "F.Cu" ); break; + case In1_Cu: txt = wxT( "In1.Cu" ); break; + case In2_Cu: txt = wxT( "In2.Cu" ); break; + case In3_Cu: txt = wxT( "In3.Cu" ); break; + case In4_Cu: txt = wxT( "In4.Cu" ); break; + case In5_Cu: txt = wxT( "In5.Cu" ); break; + case In6_Cu: txt = wxT( "In6.Cu" ); break; + case In7_Cu: txt = wxT( "In7.Cu" ); break; + case In8_Cu: txt = wxT( "In8.Cu" ); break; + case In9_Cu: txt = wxT( "In9.Cu" ); break; + case In10_Cu: txt = wxT( "In10.Cu" ); break; + case In11_Cu: txt = wxT( "In11.Cu" ); break; + case In12_Cu: txt = wxT( "In12.Cu" ); break; + case In13_Cu: txt = wxT( "In13.Cu" ); break; + case In14_Cu: txt = wxT( "In14.Cu" ); break; + case In15_Cu: txt = wxT( "In15.Cu" ); break; + case In16_Cu: txt = wxT( "In16.Cu" ); break; + case In17_Cu: txt = wxT( "In17.Cu" ); break; + case In18_Cu: txt = wxT( "In18.Cu" ); break; + case In19_Cu: txt = wxT( "In19.Cu" ); break; + case In20_Cu: txt = wxT( "In20.Cu" ); break; + case In21_Cu: txt = wxT( "In21.Cu" ); break; + case In22_Cu: txt = wxT( "In22.Cu" ); break; + case In23_Cu: txt = wxT( "In23.Cu" ); break; + case In24_Cu: txt = wxT( "In24.Cu" ); break; + case In25_Cu: txt = wxT( "In25.Cu" ); break; + case In26_Cu: txt = wxT( "In26.Cu" ); break; + case In27_Cu: txt = wxT( "In27.Cu" ); break; + case In28_Cu: txt = wxT( "In28.Cu" ); break; + case In29_Cu: txt = wxT( "In29.Cu" ); break; + case In30_Cu: txt = wxT( "In30.Cu" ); break; + case B_Cu: txt = wxT( "B.Cu" ); break; + + // Technicals + case B_Adhes: txt = wxT( "B.Adhes" ); break; + case F_Adhes: txt = wxT( "F.Adhes" ); break; + case B_Paste: txt = wxT( "B.Paste" ); break; + case F_Paste: txt = wxT( "F.Paste" ); break; + case B_SilkS: txt = wxT( "B.SilkS" ); break; + case F_SilkS: txt = wxT( "F.SilkS" ); break; + case B_Mask: txt = wxT( "B.Mask" ); break; + case F_Mask: txt = wxT( "F.Mask" ); break; + + // Users + case Dwgs_User: txt = wxT( "Dwgs.User" ); break; + case Cmts_User: txt = wxT( "Cmts.User" ); break; + case Eco1_User: txt = wxT( "Eco1.User" ); break; + case Eco2_User: txt = wxT( "Eco2.User" ); break; + case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break; + case Margin: txt = wxT( "Margin" ); break; + + // Footprint + case F_CrtYd: txt = wxT( "F.CrtYd" ); break; + case B_CrtYd: txt = wxT( "B.CrtYd" ); break; + case F_Fab: txt = wxT( "F.Fab" ); break; + case B_Fab: txt = wxT( "B.Fab" ); break; + + default: + wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) ); + txt = wxT( "BAD INDEX!" ); break; + } + + return wxString( txt ); +} diff --git a/gerbview/dialogs/dialog_show_page_borders.cpp b/gerbview/dialogs/dialog_show_page_borders.cpp new file mode 100644 index 0000000..7c2dcfd --- /dev/null +++ b/gerbview/dialogs/dialog_show_page_borders.cpp @@ -0,0 +1,84 @@ +/** + * @file dialog_show_page_borders.cpp + * Dialog to show/hide frame reference and select paper size for printing + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011 jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> +#include <macros.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <dialog_show_page_borders.h> + + +DIALOG_PAGE_SHOW_PAGE_BORDERS::DIALOG_PAGE_SHOW_PAGE_BORDERS( GERBVIEW_FRAME *parent) : + DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE( parent, wxID_ANY ) +{ + m_Parent = parent; + SetFocus(); + + m_ShowPageLimits->SetSelection(0); + + if( m_Parent->GetShowBorderAndTitleBlock() ) + { + wxString curPaperType = m_Parent->GetPageSettings().GetType(); + + for( unsigned i = 1; i<DIM( g_GerberPageSizeList ); ++i ) + { + if( curPaperType == g_GerberPageSizeList[i] ) + { + m_ShowPageLimits->SetSelection( i ); + break; + } + } + } + + GetSizer()->Fit( this ); + GetSizer()->SetSizeHints( this ); + Center(); + m_sdbSizer1OK->SetDefault(); +} + + +void DIALOG_PAGE_SHOW_PAGE_BORDERS::OnCancelButtonClick( wxCommandEvent& event ) +{ + EndModal( wxID_CANCEL ); +} + + +void DIALOG_PAGE_SHOW_PAGE_BORDERS::OnOKBUttonClick( wxCommandEvent& event ) +{ + int idx = m_ShowPageLimits->GetSelection(); + + m_Parent->SetShowBorderAndTitleBlock( idx > 0 ? true : false ); + + m_Parent->SetPageSettings( PAGE_INFO( g_GerberPageSizeList[idx] ) ); + + EndModal( wxID_OK ); +} + diff --git a/gerbview/dialogs/dialog_show_page_borders.h b/gerbview/dialogs/dialog_show_page_borders.h new file mode 100644 index 0000000..1c86686 --- /dev/null +++ b/gerbview/dialogs/dialog_show_page_borders.h @@ -0,0 +1,47 @@ +/** + * @file dialog_show_page_borders.h + * Dialog to show/hide frame reference and select paper size for printing + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011 jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <dialog_show_page_borders_base.h> + + +class DIALOG_PAGE_SHOW_PAGE_BORDERS : public DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE +{ +private: + GERBVIEW_FRAME* m_Parent; + +public: + + DIALOG_PAGE_SHOW_PAGE_BORDERS( GERBVIEW_FRAME* parent ); + ~DIALOG_PAGE_SHOW_PAGE_BORDERS() {}; + +private: + void OnOKBUttonClick( wxCommandEvent& event ); + void OnCancelButtonClick( wxCommandEvent& event ); +}; + diff --git a/gerbview/dialogs/dialog_show_page_borders_base.cpp b/gerbview/dialogs/dialog_show_page_borders_base.cpp new file mode 100644 index 0000000..9e19938 --- /dev/null +++ b/gerbview/dialogs/dialog_show_page_borders_base.cpp @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_show_page_borders_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bDialogSizer; + bDialogSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bUpperSizer; + bUpperSizer = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bRightSizer; + bRightSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_ShowPageLimitsChoices[] = { _("Full size. Do not show page limits"), _("Full size"), _("Size A4"), _("Size A3"), _("Size A2"), _("Size A"), _("Size B"), _("Size C") }; + int m_ShowPageLimitsNChoices = sizeof( m_ShowPageLimitsChoices ) / sizeof( wxString ); + m_ShowPageLimits = new wxRadioBox( this, wxID_ANY, _("Show Page Limits:"), wxDefaultPosition, wxDefaultSize, m_ShowPageLimitsNChoices, m_ShowPageLimitsChoices, 1, wxRA_SPECIFY_COLS ); + m_ShowPageLimits->SetSelection( 0 ); + bRightSizer->Add( m_ShowPageLimits, 0, wxALL|wxEXPAND, 5 ); + + + bUpperSizer->Add( bRightSizer, 1, wxEXPAND, 5 ); + + + bDialogSizer->Add( bUpperSizer, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bDialogSizer->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); + + bDialogSizer->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 ); + + + this->SetSizer( bDialogSizer ); + this->Layout(); + + // Connect Events + m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::OnCancelButtonClick ), NULL, this ); + m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::OnOKBUttonClick ), NULL, this ); +} + +DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::~DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE() +{ + // Disconnect Events + m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::OnCancelButtonClick ), NULL, this ); + m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE::OnOKBUttonClick ), NULL, this ); + +} diff --git a/gerbview/dialogs/dialog_show_page_borders_base.fbp b/gerbview/dialogs/dialog_show_page_borders_base.fbp new file mode 100644 index 0000000..3872fe6 --- /dev/null +++ b/gerbview/dialogs/dialog_show_page_borders_base.fbp @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="11" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">dialog_show_page_borders_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">dialog_show_page_borders_base</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="use_enum">0</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE</property> + <property name="pos"></property> + <property name="size">263,254</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Page Borders</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bDialogSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bUpperSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bRightSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Full size. Do not show page limits" "Full size" "Size A4" "Size A3" "Size A2" "Size A" "Size B" "Size C"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Show Page Limits:</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_ShowPageLimits</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">0</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticline1</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_HORIZONTAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxALL</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">0</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizer1</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick"></event> + <event name="OnCancelButtonClick">OnCancelButtonClick</event> + <event name="OnContextHelpButtonClick"></event> + <event name="OnHelpButtonClick"></event> + <event name="OnNoButtonClick"></event> + <event name="OnOKButtonClick">OnOKBUttonClick</event> + <event name="OnSaveButtonClick"></event> + <event name="OnYesButtonClick"></event> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/gerbview/dialogs/dialog_show_page_borders_base.h b/gerbview/dialogs/dialog_show_page_borders_base.h new file mode 100644 index 0000000..4203815 --- /dev/null +++ b/gerbview/dialogs/dialog_show_page_borders_base.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_SHOW_PAGE_BORDERS_BASE_H__ +#define __DIALOG_SHOW_PAGE_BORDERS_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +#include "dialog_shim.h" +#include <wx/string.h> +#include <wx/radiobox.h> +#include <wx/gdicmn.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/sizer.h> +#include <wx/statline.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxRadioBox* m_ShowPageLimits; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnCancelButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOKBUttonClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Page Borders"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 263,254 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_PAGE_SHOW_PAGE_BORDERS_BASE(); + +}; + +#endif //__DIALOG_SHOW_PAGE_BORDERS_BASE_H__ diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp new file mode 100644 index 0000000..d64bac5 --- /dev/null +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp @@ -0,0 +1,182 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2016 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview_dialog_display_options_frame.cpp + * Set some display options for GerbView + */ + + +#include <fctsys.h> +#include <common.h> +#include <macros.h> +#include <class_drawpanel.h> + +#include <pcbplot.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <gerbview_dialog_display_options_frame_base.h> + + +/*******************************************/ +/* Dialog frame to select display options */ +/*******************************************/ +class DIALOG_DISPLAY_OPTIONS : public DIALOG_DISPLAY_OPTIONS_BASE +{ +private: + GERBVIEW_FRAME* m_Parent; + +public: + + DIALOG_DISPLAY_OPTIONS( GERBVIEW_FRAME* parent ); + ~DIALOG_DISPLAY_OPTIONS() {}; + +private: + void OnOKBUttonClick( wxCommandEvent& event ); + void OnCancelButtonClick( wxCommandEvent& event ); + void initOptDialog( ); + void OnMiddleBtnPanEnbl( wxCommandEvent& event ) + { + m_OptMiddleButtonPanLimited->Enable( m_OptMiddleButtonPan->GetValue() ); + } +}; + + +void GERBVIEW_FRAME::InstallGerberOptionsDialog( wxCommandEvent& event ) +{ + DIALOG_DISPLAY_OPTIONS dlg( this ); + int opt = dlg.ShowModal(); + + if( opt > 0 ) + m_canvas->Refresh(); +} + + +DIALOG_DISPLAY_OPTIONS::DIALOG_DISPLAY_OPTIONS( GERBVIEW_FRAME *parent) : + DIALOG_DISPLAY_OPTIONS_BASE( parent, wxID_ANY ) +{ + m_Parent = parent; + SetFocus(); + initOptDialog( ); + + GetSizer()->Fit( this ); + GetSizer()->SetSizeHints( this ); + Center(); + m_sdbSizer1OK->SetDefault(); +} + + +void DIALOG_DISPLAY_OPTIONS::OnCancelButtonClick( wxCommandEvent& event ) +{ + EndModal( 0 ); +} + + +void DIALOG_DISPLAY_OPTIONS::initOptDialog( ) +{ + m_PolarDisplay->SetSelection( m_Parent->m_DisplayOptions.m_DisplayPolarCood ? 1 : 0 ); + m_BoxUnits->SetSelection( g_UserUnit ? 1 : 0 ); + m_CursorShape->SetSelection( m_Parent->GetCursorShape() ? 1 : 0 ); + + // Show Option Draw Lines. We use DisplayPcbTrackFill as Lines draw option + m_OptDisplayLines->SetSelection( m_Parent->m_DisplayOptions.m_DisplayLinesFill ? 1 : 0 ); + m_OptDisplayFlashedItems->SetSelection( m_Parent->m_DisplayOptions.m_DisplayFlashedItemsFill ? 1 : 0); + + // Show Option Draw polygons + m_OptDisplayPolygons->SetSelection( m_Parent->m_DisplayOptions.m_DisplayPolygonsFill ? 1 : 0 ); + + m_ShowPageLimits->SetSelection(0); + + if( m_Parent->GetShowBorderAndTitleBlock() ) + { + wxString curPaperType = m_Parent->GetPageSettings().GetType(); + + for( unsigned i = 1; i < DIM( g_GerberPageSizeList ); ++i ) + { + if( g_GerberPageSizeList[i] == curPaperType ) + { + m_ShowPageLimits->SetSelection( i ); + break; + } + } + } + + m_OptDisplayDCodes->SetValue( m_Parent->IsElementVisible( DCODES_VISIBLE ) ); + + + m_OptZoomNoCenter->SetValue( m_Parent->GetCanvas()->GetEnableZoomNoCenter() ); + m_OptMousewheelPan->SetValue( m_Parent->GetCanvas()->GetEnableMousewheelPan() ); + m_OptMiddleButtonPan->SetValue( m_Parent->GetCanvas()->GetEnableMiddleButtonPan() ); + m_OptMiddleButtonPanLimited->SetValue( m_Parent->GetCanvas()->GetMiddleButtonPanLimited() ); + m_OptMiddleButtonPanLimited->Enable( m_OptMiddleButtonPan->GetValue() ); +} + + +void DIALOG_DISPLAY_OPTIONS::OnOKBUttonClick( wxCommandEvent& event ) +{ + m_Parent->m_DisplayOptions.m_DisplayPolarCood = + (m_PolarDisplay->GetSelection() == 0) ? false : true; + g_UserUnit = (m_BoxUnits->GetSelection() == 0) ? INCHES : MILLIMETRES; + m_Parent->SetCursorShape( m_CursorShape->GetSelection() ); + + if( m_OptDisplayLines->GetSelection() == 1 ) + m_Parent->m_DisplayOptions.m_DisplayLinesFill = true; + else + m_Parent->m_DisplayOptions.m_DisplayLinesFill = false; + + if( m_OptDisplayFlashedItems->GetSelection() == 1 ) + { + m_Parent->m_DisplayOptions.m_DisplayFlashedItemsFill = true; + } + else + { + m_Parent->m_DisplayOptions.m_DisplayFlashedItemsFill = false; + } + + + if( m_OptDisplayPolygons->GetSelection() == 0 ) + m_Parent->m_DisplayOptions.m_DisplayPolygonsFill = false; + else + m_Parent->m_DisplayOptions.m_DisplayPolygonsFill = true; + + m_Parent->SetElementVisibility( DCODES_VISIBLE, m_OptDisplayDCodes->GetValue() ); + + int idx = m_ShowPageLimits->GetSelection(); + + m_Parent->SetShowBorderAndTitleBlock( idx > 0 ? true : false ); + + PAGE_INFO pageInfo( g_GerberPageSizeList[idx] ); + + m_Parent->SetPageSettings( pageInfo ); + + m_Parent->GetCanvas()->SetEnableZoomNoCenter( m_OptZoomNoCenter->GetValue() ); + m_Parent->GetCanvas()->SetEnableMousewheelPan( m_OptMousewheelPan->GetValue() ); + m_Parent->GetCanvas()->SetEnableMiddleButtonPan( m_OptMiddleButtonPan->GetValue() ); + m_Parent->GetCanvas()->SetMiddleButtonPanLimited( m_OptMiddleButtonPanLimited->GetValue() ); + + m_Parent->GetCanvas()->Refresh(); + + EndModal( 1 ); +} + diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp new file mode 100644 index 0000000..c6bdd8f --- /dev/null +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp @@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "gerbview_dialog_display_options_frame_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_DISPLAY_OPTIONS_BASE::DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bDialogSizer; + bDialogSizer = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bUpperSizer; + bUpperSizer = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bLeftSizer; + bLeftSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_PolarDisplayChoices[] = { _("Cartesian coordinates"), _("Polar coordinates") }; + int m_PolarDisplayNChoices = sizeof( m_PolarDisplayChoices ) / sizeof( wxString ); + m_PolarDisplay = new wxRadioBox( this, wxID_ANY, _("Coordinates"), wxDefaultPosition, wxDefaultSize, m_PolarDisplayNChoices, m_PolarDisplayChoices, 1, wxRA_SPECIFY_COLS ); + m_PolarDisplay->SetSelection( 0 ); + bLeftSizer->Add( m_PolarDisplay, 0, wxALL|wxEXPAND, 5 ); + + wxString m_BoxUnitsChoices[] = { _("Inches"), _("Millimeters") }; + int m_BoxUnitsNChoices = sizeof( m_BoxUnitsChoices ) / sizeof( wxString ); + m_BoxUnits = new wxRadioBox( this, wxID_ANY, _("Units"), wxDefaultPosition, wxDefaultSize, m_BoxUnitsNChoices, m_BoxUnitsChoices, 1, wxRA_SPECIFY_COLS ); + m_BoxUnits->SetSelection( 0 ); + bLeftSizer->Add( m_BoxUnits, 0, wxALL|wxEXPAND, 5 ); + + wxString m_CursorShapeChoices[] = { _("Small cross"), _("Full screen cursor") }; + int m_CursorShapeNChoices = sizeof( m_CursorShapeChoices ) / sizeof( wxString ); + m_CursorShape = new wxRadioBox( this, wxID_ANY, _("Cursor"), wxDefaultPosition, wxDefaultSize, m_CursorShapeNChoices, m_CursorShapeChoices, 1, wxRA_SPECIFY_COLS ); + m_CursorShape->SetSelection( 1 ); + bLeftSizer->Add( m_CursorShape, 0, wxALL|wxEXPAND, 5 ); + + m_OptDisplayDCodes = new wxCheckBox( this, wxID_ANY, _("Show D codes"), wxDefaultPosition, wxDefaultSize, 0 ); + m_OptDisplayDCodes->SetValue(true); + bLeftSizer->Add( m_OptDisplayDCodes, 0, wxALL, 5 ); + + + bUpperSizer->Add( bLeftSizer, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bMiddleSizer; + bMiddleSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_OptDisplayLinesChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayLinesNChoices = sizeof( m_OptDisplayLinesChoices ) / sizeof( wxString ); + m_OptDisplayLines = new wxRadioBox( this, wxID_ANY, _("Lines"), wxDefaultPosition, wxDefaultSize, m_OptDisplayLinesNChoices, m_OptDisplayLinesChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayLines->SetSelection( 1 ); + bMiddleSizer->Add( m_OptDisplayLines, 0, wxALL|wxEXPAND, 5 ); + + wxString m_OptDisplayFlashedItemsChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayFlashedItemsNChoices = sizeof( m_OptDisplayFlashedItemsChoices ) / sizeof( wxString ); + m_OptDisplayFlashedItems = new wxRadioBox( this, wxID_ANY, _("Pads"), wxDefaultPosition, wxDefaultSize, m_OptDisplayFlashedItemsNChoices, m_OptDisplayFlashedItemsChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayFlashedItems->SetSelection( 1 ); + bMiddleSizer->Add( m_OptDisplayFlashedItems, 0, wxALL|wxEXPAND, 5 ); + + wxString m_OptDisplayPolygonsChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayPolygonsNChoices = sizeof( m_OptDisplayPolygonsChoices ) / sizeof( wxString ); + m_OptDisplayPolygons = new wxRadioBox( this, wxID_ANY, _("Polygons"), wxDefaultPosition, wxDefaultSize, m_OptDisplayPolygonsNChoices, m_OptDisplayPolygonsChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayPolygons->SetSelection( 1 ); + bMiddleSizer->Add( m_OptDisplayPolygons, 0, wxALL|wxEXPAND, 5 ); + + + bUpperSizer->Add( bMiddleSizer, 1, wxALL|wxEXPAND, 5 ); + + wxBoxSizer* bRightSizer; + bRightSizer = new wxBoxSizer( wxVERTICAL ); + + wxString m_ShowPageLimitsChoices[] = { _("Full size without limits"), _("Full size"), _("Size A4"), _("Size A3"), _("Size A2"), _("Size A"), _("Size B"), _("Size C") }; + int m_ShowPageLimitsNChoices = sizeof( m_ShowPageLimitsChoices ) / sizeof( wxString ); + m_ShowPageLimits = new wxRadioBox( this, wxID_ANY, _("Page"), wxDefaultPosition, wxDefaultSize, m_ShowPageLimitsNChoices, m_ShowPageLimitsChoices, 1, wxRA_SPECIFY_COLS ); + m_ShowPageLimits->SetSelection( 0 ); + bRightSizer->Add( m_ShowPageLimits, 0, wxALL|wxEXPAND, 5 ); + + wxStaticBoxSizer* bLeftBottomSizer; + bLeftBottomSizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Pan and Zoom") ), wxVERTICAL ); + + m_OptZoomNoCenter = new wxCheckBox( bLeftBottomSizer->GetStaticBox(), wxID_ANY, _("Do not center and warp cursor on zoom"), wxDefaultPosition, wxDefaultSize, 0 ); + m_OptZoomNoCenter->SetToolTip( _("Keep the cursor at its current location when zooming") ); + + bLeftBottomSizer->Add( m_OptZoomNoCenter, 0, wxLEFT|wxRIGHT|wxTOP, 5 ); + + m_OptMiddleButtonPan = new wxCheckBox( bLeftBottomSizer->GetStaticBox(), wxID_ANY, _("Use middle mouse button to pan"), wxDefaultPosition, wxDefaultSize, 0 ); + bLeftBottomSizer->Add( m_OptMiddleButtonPan, 0, wxLEFT|wxRIGHT|wxTOP, 5 ); + + m_OptMiddleButtonPanLimited = new wxCheckBox( bLeftBottomSizer->GetStaticBox(), wxID_ANY, _("Limit panning to scroll size"), wxDefaultPosition, wxDefaultSize, 0 ); + bLeftBottomSizer->Add( m_OptMiddleButtonPanLimited, 0, wxLEFT|wxRIGHT|wxTOP, 5 ); + + m_OptMousewheelPan = new wxCheckBox( bLeftBottomSizer->GetStaticBox(), wxID_ANY, _("Use touchpad to pan"), wxDefaultPosition, wxDefaultSize, 0 ); + m_OptMousewheelPan->SetToolTip( _("Use touchpad to pan canvas") ); + + bLeftBottomSizer->Add( m_OptMousewheelPan, 0, wxALL, 5 ); + + + bRightSizer->Add( bLeftBottomSizer, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + + bUpperSizer->Add( bRightSizer, 2, wxALL|wxEXPAND, 5 ); + + + bDialogSizer->Add( bUpperSizer, 1, wxEXPAND, 5 ); + + m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); + bDialogSizer->Add( m_staticline1, 0, wxEXPAND|wxLEFT|wxRIGHT, 5 ); + + m_sdbSizer1 = new wxStdDialogButtonSizer(); + m_sdbSizer1OK = new wxButton( this, wxID_OK ); + m_sdbSizer1->AddButton( m_sdbSizer1OK ); + m_sdbSizer1Cancel = new wxButton( this, wxID_CANCEL ); + m_sdbSizer1->AddButton( m_sdbSizer1Cancel ); + m_sdbSizer1->Realize(); + + bDialogSizer->Add( m_sdbSizer1, 0, wxEXPAND|wxALL, 5 ); + + + this->SetSizer( bDialogSizer ); + this->Layout(); + bDialogSizer->Fit( this ); + + // Connect Events + m_OptMiddleButtonPan->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnMiddleBtnPanEnbl ), NULL, this ); + m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnCancelButtonClick ), NULL, this ); + m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnOKBUttonClick ), NULL, this ); +} + +DIALOG_DISPLAY_OPTIONS_BASE::~DIALOG_DISPLAY_OPTIONS_BASE() +{ + // Disconnect Events + m_OptMiddleButtonPan->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnMiddleBtnPanEnbl ), NULL, this ); + m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnCancelButtonClick ), NULL, this ); + m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_DISPLAY_OPTIONS_BASE::OnOKBUttonClick ), NULL, this ); + +} diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp new file mode 100644 index 0000000..4c57b25 --- /dev/null +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp @@ -0,0 +1,1334 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="13" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">gerbview_dialog_display_options_frame_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="internationalize">1</property> + <property name="name">gerbview_dialog_display_options_frame_base</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_lua_events">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="ui_table">UI</property> + <property name="use_enum">0</property> + <property name="use_microsoft_bom">0</property> + <object class="Dialog" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="center"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="extra_style"></property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">DIALOG_DISPLAY_OPTIONS_BASE</property> + <property name="pos"></property> + <property name="size">-1,-1</property> + <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property> + <property name="subclass">DIALOG_SHIM; dialog_shim.h</property> + <property name="title">Gerbview Options</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnActivate"></event> + <event name="OnActivateApp"></event> + <event name="OnAuiFindManager"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnChar"></event> + <event name="OnClose"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnHibernate"></event> + <event name="OnIconize"></event> + <event name="OnIdle"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bDialogSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bUpperSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bLeftSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Cartesian coordinates" "Polar coordinates"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Coordinates</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_PolarDisplay</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">0</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Inches" "Millimeters"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Units</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_BoxUnits</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">0</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Small cross" "Full screen cursor"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Cursor</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_CursorShape</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">1</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Show D codes</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptDisplayDCodes</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bMiddleSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Sketch" "Filled"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Lines</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptDisplayLines</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Sketch" "Filled"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Pads</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptDisplayFlashedItems</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Sketch" "Filled"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Polygons</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptDisplayPolygons</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">1</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">2</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bRightSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">0</property> + <object class="wxRadioBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="choices">"Full size without limits" "Full size" "Size A4" "Size A3" "Size A2" "Size A" "Size B" "Size C"</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Page</property> + <property name="majorDimension">1</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_ShowPageLimits</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="selection">0</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxRA_SPECIFY_COLS</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRadioBox"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxStaticBoxSizer" expanded="1"> + <property name="id">wxID_ANY</property> + <property name="label">Pan and Zoom</property> + <property name="minimum_size"></property> + <property name="name">bLeftBottomSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <event name="OnUpdateUI"></event> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxLEFT|wxRIGHT|wxTOP</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Do not center and warp cursor on zoom</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptZoomNoCenter</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip">Keep the cursor at its current location when zooming</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="0"> + <property name="border">5</property> + <property name="flag">wxLEFT|wxRIGHT|wxTOP</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="0"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Use middle mouse button to pan</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptMiddleButtonPan</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox">OnMiddleBtnPanEnbl</event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxLEFT|wxRIGHT|wxTOP</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Limit panning to scroll size</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptMiddleButtonPanLimited</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxCheckBox" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="checked">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Use touchpad to pan</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_OptMousewheelPan</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip">Use touchpad to pan canvas</property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnCheckBox"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxLEFT|wxRIGHT</property> + <property name="proportion">0</property> + <object class="wxStaticLine" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_staticline1</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style">wxLI_HORIZONTAL</property> + <property name="subclass"></property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnChar"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxEXPAND|wxALL</property> + <property name="proportion">0</property> + <object class="wxStdDialogButtonSizer" expanded="1"> + <property name="Apply">0</property> + <property name="Cancel">1</property> + <property name="ContextHelp">0</property> + <property name="Help">0</property> + <property name="No">0</property> + <property name="OK">1</property> + <property name="Save">0</property> + <property name="Yes">0</property> + <property name="minimum_size"></property> + <property name="name">m_sdbSizer1</property> + <property name="permission">protected</property> + <event name="OnApplyButtonClick"></event> + <event name="OnCancelButtonClick">OnCancelButtonClick</event> + <event name="OnContextHelpButtonClick"></event> + <event name="OnHelpButtonClick"></event> + <event name="OnNoButtonClick"></event> + <event name="OnOKButtonClick">OnOKBUttonClick</event> + <event name="OnSaveButtonClick"></event> + <event name="OnYesButtonClick"></event> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h new file mode 100644 index 0000000..d49eea1 --- /dev/null +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jun 17 2015) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __GERBVIEW_DIALOG_DISPLAY_OPTIONS_FRAME_BASE_H__ +#define __GERBVIEW_DIALOG_DISPLAY_OPTIONS_FRAME_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +#include <wx/intl.h> +class DIALOG_SHIM; + +#include "dialog_shim.h" +#include <wx/string.h> +#include <wx/radiobox.h> +#include <wx/gdicmn.h> +#include <wx/font.h> +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/checkbox.h> +#include <wx/sizer.h> +#include <wx/statbox.h> +#include <wx/statline.h> +#include <wx/button.h> +#include <wx/dialog.h> + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_DISPLAY_OPTIONS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_DISPLAY_OPTIONS_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxRadioBox* m_PolarDisplay; + wxRadioBox* m_BoxUnits; + wxRadioBox* m_CursorShape; + wxCheckBox* m_OptDisplayDCodes; + wxRadioBox* m_OptDisplayLines; + wxRadioBox* m_OptDisplayFlashedItems; + wxRadioBox* m_OptDisplayPolygons; + wxRadioBox* m_ShowPageLimits; + wxCheckBox* m_OptZoomNoCenter; + wxCheckBox* m_OptMiddleButtonPan; + wxCheckBox* m_OptMiddleButtonPanLimited; + wxCheckBox* m_OptMousewheelPan; + wxStaticLine* m_staticline1; + wxStdDialogButtonSizer* m_sdbSizer1; + wxButton* m_sdbSizer1OK; + wxButton* m_sdbSizer1Cancel; + + // Virtual event handlers, overide them in your derived class + virtual void OnMiddleBtnPanEnbl( wxCommandEvent& event ) { event.Skip(); } + virtual void OnCancelButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnOKBUttonClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Gerbview Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_DISPLAY_OPTIONS_BASE(); + +}; + +#endif //__GERBVIEW_DIALOG_DISPLAY_OPTIONS_FRAME_BASE_H__ diff --git a/gerbview/draw_gerber_screen.cpp b/gerbview/draw_gerber_screen.cpp new file mode 100644 index 0000000..2ae6f4a --- /dev/null +++ b/gerbview/draw_gerber_screen.cpp @@ -0,0 +1,457 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jpierre.charras at wanadoo + * Copyright (C) 2013-2015 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file draw_gerber_screen.cpp + */ + + +#include <fctsys.h> +#include <gr_basic.h> +#include <common.h> +#include <class_drawpanel.h> +#include <drawtxt.h> +#include <base_units.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <colors_selection.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> +#include <printout_controler.h> + + +void GERBVIEW_FRAME::PrintPage( wxDC* aDC, LSET aPrintMasklayer, + bool aPrintMirrorMode, void* aData ) +{ + wxCHECK_RET( aData != NULL, wxT( "aData cannot be NULL." ) ); + + // Save current draw options, because print mode has specific options: + GBR_DISPLAY_OPTIONS imgDisplayOptions = m_DisplayOptions; + std::bitset <GERBER_DRAWLAYERS_COUNT> printLayersMask = GetGerberLayout()->GetPrintableLayers(); + + // Set draw options for printing: + m_DisplayOptions.m_DisplayFlashedItemsFill = true; + m_DisplayOptions.m_DisplayLinesFill = true; + m_DisplayOptions.m_DisplayPolygonsFill = true; + m_DisplayOptions.m_DisplayDCodes = false; + m_DisplayOptions.m_IsPrinting = true; + + PRINT_PARAMETERS* printParameters = (PRINT_PARAMETERS*) aData; + + // Find the layer to be printed + int page = printParameters->m_Flags; // contains the page number (not necessarily layer number) + int layer = 0; + + // Find the layer number for the printed page (search through the mask and count bits) + while( page > 0 ) + { + if( printLayersMask[layer++] ) + --page; + } + --layer; + + std::bitset <GERBER_DRAWLAYERS_COUNT> printCurrLayerMask; + printCurrLayerMask.reset(); + printCurrLayerMask.set( layer ); + GetGerberLayout()->SetPrintableLayers( printCurrLayerMask ); + m_canvas->SetPrintMirrored( aPrintMirrorMode ); + bool printBlackAndWhite = printParameters->m_Print_Black_and_White; + + GetGerberLayout()->Draw( m_canvas, aDC, (GR_DRAWMODE) 0, + wxPoint( 0, 0 ), printBlackAndWhite ); + + m_canvas->SetPrintMirrored( false ); + + // Restore draw options: + GetGerberLayout()->SetPrintableLayers( printLayersMask ); + m_DisplayOptions = imgDisplayOptions; +} + + +void GERBVIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg ) +{ + GBR_SCREEN* screen = (GBR_SCREEN*) GetScreen(); + + if( !GetGerberLayout() ) + return; + + wxBusyCursor dummy; + + GR_DRAWMODE drawMode = UNSPECIFIED_DRAWMODE; + + switch( GetDisplayMode() ) + { + default: + case 0: + break; + + case 1: + drawMode = GR_COPY; + break; + + case 2: + drawMode = GR_OR; + break; + } + + // Draw according to the current setting. This needs to be GR_COPY or GR_OR. + GetGerberLayout()->Draw( m_canvas, DC, drawMode, wxPoint( 0, 0 ) ); + + // Draw the "background" now, i.e. grid and axis after gerber layers + // because most of time the actual background is erased by successive drawings of each gerber + // layer mainly in COPY mode + m_canvas->DrawBackGround( DC ); + + if( IsElementVisible( DCODES_VISIBLE ) ) + DrawItemsDCodeID( DC, GR_COPY ); + + DrawWorkSheet( DC, screen, 0, IU_PER_MILS, wxEmptyString ); + +#ifdef USE_WX_OVERLAY + if( IsShown() ) + { + m_overlay.Reset(); + wxDCOverlay overlaydc( m_overlay, (wxWindowDC*)DC ); + overlaydc.Clear(); + } +#endif + + if( m_canvas->IsMouseCaptured() ) + m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + + m_canvas->DrawCrossHair( DC ); + + // Display the filename and the layer name (found in the gerber files, if any) + // relative to the active layer + UpdateTitleAndInfo(); +} + + +/* + * Redraw All GerbView layers, using a buffered mode or not + */ +void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, + const wxPoint& aOffset, bool aPrintBlackAndWhite ) +{ + GERBVIEW_FRAME* gerbFrame = (GERBVIEW_FRAME*) aPanel->GetParent(); + + // Because Images can be negative (i.e with background filled in color) items are drawn + // graphic layer per graphic layer, after the background is filled + // to a temporary bitmap + // at least when aDrawMode = GR_COPY or aDrawMode = GR_OR + // If aDrawMode = UNSPECIFIED_DRAWMODE, items are drawn to the main screen, and therefore + // artifacts can happen with negative items or negative images + + wxColour bgColor = MakeColour( gerbFrame->GetDrawBgColor() ); + wxBrush bgBrush( bgColor, wxBRUSHSTYLE_SOLID ); + + int bitmapWidth, bitmapHeight; + wxDC* plotDC = aDC; + + aPanel->GetClientSize( &bitmapWidth, &bitmapHeight ); + + wxBitmap* layerBitmap = NULL; + wxBitmap* screenBitmap = NULL; + wxMemoryDC layerDC; // used sequentially for each gerber layer + wxMemoryDC screenDC; + + // When each image must be drawn using GR_OR (transparency mode) + // or GR_COPY (stacked mode) we must use a temporary bitmap + // to draw gerber images. + // this is due to negative objects (drawn using background color) that create artifacts + // on other images when drawn on screen + bool useBufferBitmap = false; + +#ifndef __WXMAC__ + // Can't work with MAC + // Don't try this with retina display + if( (aDrawMode == GR_COPY) || ( aDrawMode == GR_OR ) ) + useBufferBitmap = true; +#endif + + // these parameters are saved here, because they are modified + // and restored later + EDA_RECT drawBox = *aPanel->GetClipBox(); + double scale; + aDC->GetUserScale(&scale, &scale); + wxPoint dev_org = aDC->GetDeviceOrigin(); + wxPoint logical_org = aDC->GetLogicalOrigin( ); + + + if( useBufferBitmap ) + { + layerBitmap = new wxBitmap( bitmapWidth, bitmapHeight ); + screenBitmap = new wxBitmap( bitmapWidth, bitmapHeight ); + layerDC.SelectObject( *layerBitmap ); + aPanel->DoPrepareDC( layerDC ); + aPanel->SetClipBox( drawBox ); + layerDC.SetBackground( bgBrush ); + layerDC.SetBackgroundMode( wxSOLID ); + layerDC.Clear(); + + screenDC.SelectObject( *screenBitmap ); + screenDC.SetBackground( bgBrush ); + screenDC.SetBackgroundMode( wxSOLID ); + screenDC.Clear(); + + plotDC = &layerDC; + } + + bool doBlit = false; // this flag requests an image transfer to actual screen when true. + + bool end = false; + + // Draw layers from bottom to top, and active layer last + // in non transparent modes, the last layer drawn mask mask previously drawn layer + for( int layer = GERBER_DRAWLAYERS_COUNT-1; !end; --layer ) + { + int active_layer = gerbFrame->getActiveLayer(); + + if( layer == active_layer ) // active layer will be drawn after other layers + continue; + + if( layer < 0 ) // last loop: draw active layer + { + end = true; + layer = active_layer; + } + + if( !gerbFrame->IsLayerVisible( layer ) ) + continue; + + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); + + if( gerber == NULL ) // Graphic layer not yet used + continue; + + EDA_COLOR_T color = gerbFrame->GetLayerColor( layer ); + + // Force black and white draw mode on request: + if( aPrintBlackAndWhite ) + gerbFrame->SetLayerColor( layer, gerbFrame->GetDrawBgColor() == BLACK ? WHITE : BLACK ); + + if( useBufferBitmap ) + { + // Draw each layer into a bitmap first. Negative Gerber + // layers are drawn in background color. + if( gerber->HasNegativeItems() && doBlit ) + { + // Set Device origin, logical origin and scale to default values + // This is needed by Blit function when using a mask. + // Beside, for Blit call, both layerDC and screenDc must have the same settings + layerDC.SetDeviceOrigin(0,0); + layerDC.SetLogicalOrigin( 0, 0 ); + layerDC.SetUserScale( 1, 1 ); + + if( aDrawMode == GR_COPY ) + { + // Use the layer bitmap itself as a mask when blitting. The bitmap + // cannot be referenced by a device context when setting the mask. + layerDC.SelectObject( wxNullBitmap ); + layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) ); + layerDC.SelectObject( *layerBitmap ); + screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true ); + } + else if( aDrawMode == GR_OR ) + { + // On Linux with a large screen, this version is much faster and without + // flicker, but gives a Pcbnew look where layer colors blend together. + // Plus it works only because the background color is black. But it may + // be more usable for some. The difference is due in part because of + // the cpu cycles needed to create the monochromatic bitmap above, and + // the extra time needed to do bit indexing into the monochromatic bitmap + // on the blit above. + screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR ); + } + // Restore actual values and clear bitmap for next drawing + layerDC.SetDeviceOrigin( dev_org.x, dev_org.y ); + layerDC.SetLogicalOrigin( logical_org.x, logical_org.y ); + layerDC.SetUserScale( scale, scale ); + layerDC.SetBackground( bgBrush ); + layerDC.SetBackgroundMode( wxSOLID ); + layerDC.Clear(); + + doBlit = false; + } + + } + + if( gerber->m_ImageNegative ) + { + // Draw background negative (i.e. in graphic layer color) for negative images. + EDA_COLOR_T color = gerbFrame->GetLayerColor( layer ); + + GRSetDrawMode( &layerDC, GR_COPY ); + GRFilledRect( &drawBox, plotDC, drawBox.GetX(), drawBox.GetY(), + drawBox.GetRight(), drawBox.GetBottom(), + 0, color, color ); + + GRSetDrawMode( plotDC, GR_COPY ); + doBlit = true; + } + + int dcode_highlight = 0; + + if( layer == gerbFrame->getActiveLayer() ) + dcode_highlight = gerber->m_Selected_Tool; + + GR_DRAWMODE layerdrawMode = GR_COPY; + + if( aDrawMode == GR_OR && !gerber->HasNegativeItems() ) + layerdrawMode = GR_OR; + + // Now we can draw the current layer to the bitmap buffer + // When needed, the previous bitmap is already copied to the screen buffer. + for( GERBER_DRAW_ITEM* item = gerbFrame->GetItemsList(); item; item = item->Next() ) + { + if( item->GetLayer() != layer ) + continue; + + GR_DRAWMODE drawMode = layerdrawMode; + + if( dcode_highlight && dcode_highlight == item->m_DCode ) + DrawModeAddHighlight( &drawMode); + + item->Draw( aPanel, plotDC, drawMode, wxPoint(0,0) ); + doBlit = true; + } + + if( aPrintBlackAndWhite ) + gerbFrame->SetLayerColor( layer, color ); + } + + if( doBlit && useBufferBitmap ) // Blit is used only if aDrawMode >= 0 + { + // For this Blit call, layerDC and screenDC must have the same settings + // So we set device origin, logical origin and scale to default values + // in layerDC + layerDC.SetDeviceOrigin(0,0); + layerDC.SetLogicalOrigin( 0, 0 ); + layerDC.SetUserScale( 1, 1 ); + + // this is the last transfer to screenDC. If there are no negative items, this is + // the only one + if( aDrawMode == GR_COPY ) + { + layerDC.SelectObject( wxNullBitmap ); + layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) ); + layerDC.SelectObject( *layerBitmap ); + screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true ); + + } + else if( aDrawMode == GR_OR ) + { + screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR ); + } + } + + if( useBufferBitmap ) + { + // For this Blit call, aDC and screenDC must have the same settings + // So we set device origin, logical origin and scale to default values + // in aDC + aDC->SetDeviceOrigin( 0, 0); + aDC->SetLogicalOrigin( 0, 0 ); + aDC->SetUserScale( 1, 1 ); + + aDC->Blit( 0, 0, bitmapWidth, bitmapHeight, &screenDC, 0, 0, wxCOPY ); + + // Restore aDC values + aDC->SetDeviceOrigin(dev_org.x, dev_org.y); + aDC->SetLogicalOrigin( logical_org.x, logical_org.y ); + aDC->SetUserScale( scale, scale ); + + layerDC.SelectObject( wxNullBitmap ); + screenDC.SelectObject( wxNullBitmap ); + delete layerBitmap; + delete screenBitmap; + } +} + + +void GERBVIEW_FRAME::DrawItemsDCodeID( wxDC* aDC, GR_DRAWMODE aDrawMode ) +{ + wxPoint pos; + int width; + double orient; + wxString Line; + + GRSetDrawMode( aDC, aDrawMode ); + + for( GERBER_DRAW_ITEM* item = GetItemsList(); item != NULL; item = item->Next() ) + { + if( IsLayerVisible( item->GetLayer() ) == false ) + continue; + + if( item->m_DCode <= 0 ) + continue; + + if( item->m_Flashed || item->m_Shape == GBR_ARC ) + { + pos = item->m_Start; + } + else + { + pos.x = (item->m_Start.x + item->m_End.x) / 2; + pos.y = (item->m_Start.y + item->m_End.y) / 2; + } + + pos = item->GetABPosition( pos ); + + Line.Printf( wxT( "D%d" ), item->m_DCode ); + + if( item->GetDcodeDescr() ) + width = item->GetDcodeDescr()->GetShapeDim( item ); + else + width = std::min( item->m_Size.x, item->m_Size.y ); + + orient = TEXT_ORIENT_HORIZ; + + if( item->m_Flashed ) + { + // A reasonable size for text is width/3 because most of time this text has 3 chars. + width /= 3; + } + else // this item is a line + { + wxPoint delta = item->m_Start - item->m_End; + + if( abs( delta.x ) < abs( delta.y ) ) + orient = TEXT_ORIENT_VERT; + + // A reasonable size for text is width/2 because text needs margin below and above it. + // a margin = width/4 seems good + width /= 2; + } + + int color = GetVisibleElementColor( DCODES_VISIBLE ); + + DrawGraphicText( m_canvas->GetClipBox(), aDC, pos, (EDA_COLOR_T) color, Line, + orient, wxSize( width, width ), + GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, + 0, false, false ); + } +} diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp new file mode 100644 index 0000000..c5a5566 --- /dev/null +++ b/gerbview/events_called_functions.cpp @@ -0,0 +1,390 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file events_called_functions.cpp + * @brief GerbView command event functions. + */ + +#include <fctsys.h> +#include <pgm_base.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <common.h> +#include <gestfich.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <kicad_device_context.h> +#include <gerbview_id.h> +#include <class_GERBER.h> +#include <dialog_helpers.h> +#include <class_DCodeSelectionbox.h> +#include <class_gerbview_layer_widget.h> +#include <dialog_show_page_borders.h> + + +// Event table: + +BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) + EVT_CLOSE( GERBVIEW_FRAME::OnCloseWindow ) + EVT_SIZE( GERBVIEW_FRAME::OnSize ) + + EVT_TOOL( wxID_FILE, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_ERASE_ALL, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_LOAD_DRILL_FILE, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_SET_PAGE_BORDER, GERBVIEW_FRAME::Process_Special_Functions ) + + // Menu Files: + EVT_MENU( wxID_FILE, GERBVIEW_FRAME::Files_io ) + EVT_MENU( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) + EVT_MENU( ID_GEN_PLOT, GERBVIEW_FRAME::ToPlotter ) + EVT_MENU( ID_GERBVIEW_EXPORT_TO_PCBNEW, GERBVIEW_FRAME::ExportDataInPcbnewFormat ) + + EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, GERBVIEW_FRAME::OnGbrFileHistory ) + EVT_MENU_RANGE( ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILE9, + GERBVIEW_FRAME::OnDrlFileHistory ) + + EVT_MENU( wxID_EXIT, GERBVIEW_FRAME::OnQuit ) + + // menu Preferences + EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, + GERBVIEW_FRAME::Process_Config ) + + EVT_MENU( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_MENU( wxID_PREFERENCES, GERBVIEW_FRAME::InstallGerberOptionsDialog ) + + // menu Postprocess + EVT_MENU( ID_GERBVIEW_SHOW_LIST_DCODES, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_MENU( ID_GERBVIEW_SHOW_SOURCE, GERBVIEW_FRAME::OnShowGerberSourceFile ) + EVT_MENU( ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, + EDA_BASE_FRAME::OnSelectPreferredEditor ) + + // menu Miscellaneous + EVT_MENU( ID_GERBVIEW_GLOBAL_DELETE, GERBVIEW_FRAME::Process_Special_Functions ) + + // Menu Help + EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) + EVT_MENU( wxID_INDEX, EDA_DRAW_FRAME::GetKicadHelp ) + EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout ) + + EVT_TOOL( wxID_UNDO, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter ) + EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + GERBVIEW_FRAME::OnSelectActiveLayer ) + + EVT_SELECT_DCODE( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnSelectActiveDCode ) + + // Vertical toolbar: + EVT_TOOL( ID_NO_TOOL_SELECTED, GERBVIEW_FRAME::Process_Special_Functions ) + + EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, + GERBVIEW_FRAME::Process_Special_Functions ) + + // Option toolbar + EVT_TOOL( ID_TB_OPTIONS_SHOW_POLAR_COORD, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, + GERBVIEW_FRAME::OnSelectDisplayMode ) + + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_POLAR_COORD, GERBVIEW_FRAME::OnUpdateCoordType ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, + GERBVIEW_FRAME::OnUpdateFlashedItemsDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnUpdateLinesDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnUpdatePolygonsDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnUpdateShowDCodes ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS, GERBVIEW_FRAME::OnUpdateShowNegativeItems ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + GERBVIEW_FRAME::OnUpdateShowLayerManager ) + + EVT_UPDATE_UI( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnUpdateSelectDCode ) + EVT_UPDATE_UI( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + GERBVIEW_FRAME::OnUpdateLayerSelectBox ) + EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, + GERBVIEW_FRAME::OnUpdateDrawMode ) + +END_EVENT_TABLE() + + +/* Handles the selection of tools, menu, and popup menu commands. + */ +void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) +{ + int id = event.GetId(); + + switch( id ) + { + case ID_POPUP_PLACE_BLOCK: + case ID_POPUP_ZOOM_BLOCK: + break; + + case ID_POPUP_CANCEL_CURRENT_COMMAND: + m_canvas->EndMouseCapture(); + + if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_IDLE ) + { + /* Should not be executed, except bug */ + GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE ); + GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK ); + GetScreen()->m_BlockLocate.ClearItemsList(); + } + + if( GetToolId() == ID_NO_TOOL_SELECTED ) + SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); + else + m_canvas->SetCursor( (wxStockCursor) m_canvas->GetCurrentCursor() ); + break; + + default: + m_canvas->EndMouseCapture(); + break; + } + + INSTALL_UNBUFFERED_DC( dc, m_canvas ); + + switch( id ) + { + case ID_GERBVIEW_SET_PAGE_BORDER: + { + DIALOG_PAGE_SHOW_PAGE_BORDERS dlg( this ); + + if( dlg.ShowModal() == wxID_OK ) + m_canvas->Refresh(); + } + break; + + case ID_GERBVIEW_GLOBAL_DELETE: + Erase_Current_DrawLayer( true ); + ClearMsgPanel(); + break; + + case ID_NO_TOOL_SELECTED: + SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); + break; + + case ID_POPUP_CLOSE_CURRENT_TOOL: + SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); + break; + + case ID_POPUP_CANCEL_CURRENT_COMMAND: + break; + + case ID_GERBVIEW_SHOW_LIST_DCODES: + Liste_D_Codes(); + break; + + case ID_POPUP_PLACE_BLOCK: + GetScreen()->m_BlockLocate.SetCommand( BLOCK_MOVE ); + m_canvas->SetAutoPanRequest( false ); + HandleBlockPlace( &dc ); + break; + + case ID_POPUP_ZOOM_BLOCK: + GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM ); + GetScreen()->m_BlockLocate.SetMessageBlock( this ); + HandleBlockEnd( &dc ); + break; + + default: + wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) ); + break; + } +} + + +void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) +{ + GERBER_IMAGE* gerber_image = g_GERBER_List.GetGbrImage( getActiveLayer() ); + + if( gerber_image ) + { + int tool = m_DCodeSelector->GetSelectedDCodeId(); + + if( tool != gerber_image->m_Selected_Tool ) + { + gerber_image->m_Selected_Tool = tool; + m_canvas->Refresh(); + } + } +} + + +void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) +{ + int layer = getActiveLayer(); + + setActiveLayer( event.GetSelection() ); + + if( layer != getActiveLayer() ) + { + if( m_LayersManager->OnLayerSelected() ) + m_canvas->Refresh(); + } +} + + +void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) +{ + int layer = getActiveLayer(); + GERBER_IMAGE* gerber_layer = g_GERBER_List.GetGbrImage( layer ); + + if( gerber_layer ) + { + wxString editorname = Pgm().GetEditorName(); + if( !editorname.IsEmpty() ) + { + wxFileName fn( gerber_layer->m_FileName ); + ExecuteFile( this, editorname, QuoteFullPath( fn ) ); + } + else + wxMessageBox( _( "No editor defined. Please select one" ) ); + } + + else + { + wxString msg; + msg.Printf( _( "No file loaded on the active layer %d" ), layer + 1 ); + wxMessageBox( msg ); + } +} + + +void GERBVIEW_FRAME::OnSelectDisplayMode( wxCommandEvent& event ) +{ + int oldMode = GetDisplayMode(); + + switch( event.GetId() ) + { + case ID_TB_OPTIONS_SHOW_GBR_MODE_0: + SetDisplayMode( 0 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_1: + SetDisplayMode( 1 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_2: + SetDisplayMode( 2 ); + break; + } + + if( GetDisplayMode() != oldMode ) + m_canvas->Refresh(); +} + + +void GERBVIEW_FRAME::OnQuit( wxCommandEvent& event ) +{ + Close( true ); +} + + +void GERBVIEW_FRAME::ShowChangedLanguage() +{ + // call my base class + EDA_DRAW_FRAME::ShowChangedLanguage(); + + m_LayersManager->SetLayersManagerTabsText(); + + wxAuiPaneInfo& pane_info = m_auimgr.GetPane( m_LayersManager ); + pane_info.Caption( _( "Visibles" ) ); + m_auimgr.Update(); + + ReFillLayerWidget(); +} + + +void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) +{ + int id = event.GetId(); + bool state; + + switch( id ) + { + case ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG: + state = ! m_show_layer_manager_tools; + id = ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR; + break; + + default: + state = m_optionsToolBar->GetToolToggled( id ); + break; + } + + switch( id ) + { + case ID_TB_OPTIONS_SHOW_POLAR_COORD: + m_DisplayOptions.m_DisplayPolarCood = state; + break; + + case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH: + m_DisplayOptions.m_DisplayFlashedItemsFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_LINES_SKETCH: + m_DisplayOptions.m_DisplayLinesFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH: + m_DisplayOptions.m_DisplayPolygonsFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_DCODES: + SetElementVisibility( DCODES_VISIBLE, state ); + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS: + SetElementVisibility( NEGATIVE_OBJECTS_VISIBLE, state ); + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR: + + // show/hide auxiliary Vertical layers and visibility manager toolbar + m_show_layer_manager_tools = state; + m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); + m_auimgr.Update(); + GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + m_show_layer_manager_tools ? + _("Hide &Layers Manager" ) : _("Show &Layers Manager" )); + break; + + default: + wxMessageBox( wxT( "GERBVIEW_FRAME::OnSelectOptionToolbar error" ) ); + break; + } +} + diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp new file mode 100644 index 0000000..54283ab --- /dev/null +++ b/gerbview/excellon_read_drill_file.cpp @@ -0,0 +1,702 @@ +/** + * @file excellon_read_drill_file.cpp + * Functions to read drill files (EXCELLON format) created by Pcbnew + * These files use only a subset of EXCELLON commands. + */ + + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2014 Jean-Pierre Charras <jp.charras at wanadoo.fr> + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Here is a sample of drill files created by Pcbnew, in decimal format: + * (Note: coordinates formats are same as Gerber, and T commands are near Gerber D commands). + * M48 + * ;DRILL file {PCBnew (2011-03-14 BZR 2894)-testing} date 15/03/2011 14:23:22 + * ;FORMAT={-:-/ absolute / inch / decimal} + * FMAT,2 + * INCH,TZ + * T1C0.02 + * T2C0.032 + * % + * G90 + * G05 + * M72 + * T1 + * X1.580Y-1.360 + * X1.580Y-4.860 + * X8.680Y-1.360 + * X8.680Y-4.860 + * T2 + * X2.930Y-3.560 + * X5.280Y-2.535 + * X5.405Y-2.610 + * X5.620Y-2.900 + * T0 + * M30 + */ + /* + * Note there are some variant of tool definition: + * T1F00S00C0.2 or T1C0.02F00S00 ... Feed Rate and Spindle Speed of Tool 1 + * Feed Rate and Spindle Speed are just skipped because they are not used in a viewer + */ + +#include <fctsys.h> +#include <common.h> +#include <confirm.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <trigo.h> +#include <macros.h> +#include <base_units.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> +#include <class_excellon.h> +#include <kicad_string.h> +#include <class_X2_gerber_attributes.h> + +#include <cmath> + +#include <html_messagebox.h> + +// Default format for dimensions +// number of digits in mantissa: +static int fmtMantissaMM = 3; +static int fmtMantissaInch = 4; +// number of digits, integer part: +static int fmtIntegerMM = 3; +static int fmtIntegerInch = 2; + +extern int ReadInt( char*& text, bool aSkipSeparator = true ); +extern double ReadDouble( char*& text, bool aSkipSeparator = true ); +extern void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem, + APERTURE_T aAperture, + int Dcode_index, + int aLayer, + const wxPoint& aPos, + wxSize aSize, + bool aLayerNegative ); +void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, + int Dcode_index, + int aLayer, + const wxPoint& aStart, + const wxPoint& aEnd, + wxSize aPenSize, + bool aLayerNegative ); + +// Getber X2 files have a file attribute which specify the type of image +// (copper, solder paste ... and sides tpo, bottom or inner copper layers) +// Excellon drill files do not have attributes, so, just to identify the image +// In gerbview, we add this attribute, like a Gerber drill file +static const char file_attribute[] = ".FileFunction,Other,Drill*"; + +static EXCELLON_CMD excellonHeaderCmdList[] = +{ + { "M0", DRILL_M_END, -1 }, // End of Program - No Rewind + { "M00", DRILL_M_END, -1 }, // End of Program - No Rewind + { "M30", DRILL_M_ENDREWIND, -1 }, // End of Program Rewind + { "M47", DRILL_M_MESSAGE, -1 }, // Operator Message + { "M45", DRILL_M_LONGMESSAGE, -1 }, // Long Operator message (use more than one line) + { "M48", DRILL_M_HEADER, 0 }, // beginning of a header + { "M95", DRILL_M_ENDHEADER, 0 }, // End of the header + { "METRIC", DRILL_METRICHEADER, 1 }, + { "INCH", DRILL_IMPERIALHEADER, 1 }, + { "M71", DRILL_M_METRIC, 1 }, + { "M72", DRILL_M_IMPERIAL, 1 }, + { "M25", DRILL_M_BEGINPATTERN, 0 }, // Beginning of Pattern + { "M01", DRILL_M_ENDPATTERN, 0 }, // End of Pattern + { "M97", DRILL_M_CANNEDTEXT, -1 }, + { "M98", DRILL_M_CANNEDTEXT, -1 }, + { "DETECT", DRILL_DETECT_BROKEN, -1 }, + { "ICI", DRILL_INCREMENTALHEADER, 1 }, + { "FMAT", DRILL_FMT, 1 }, // Use Format command + { "ATC", DRILL_AUTOMATIC_TOOL_CHANGE, 0 }, + { "TCST", DRILL_TOOL_CHANGE_STOP, 0 }, // Tool Change Stop + { "AFS", DRILL_AUTOMATIC_SPEED }, // Automatic Feeds and Speeds + { "VER", DRILL_AXIS_VERSION, 1 }, // Selection of X and Y Axis Version + { "R", DRILL_RESET_CMD, -1 }, // Reset commands + { "%", DRILL_REWIND_STOP, -1 }, // Rewind stop. End of the header + { "/", DRILL_SKIP, -1 }, // Clear Tool Linking. End of the header + // Keep this item after all commands starting by 'T': + { "T", DRILL_TOOL_INFORMATION, 0 }, // Tool Information + { "", DRILL_M_UNKNOWN, 0 } // last item in list +}; + +static EXCELLON_CMD excellon_G_CmdList[] = +{ + { "G90", DRILL_G_ABSOLUTE, 0 }, // Absolute Mode + { "G91", DRILL_G_INCREMENTAL, 0 }, // Incremental Input Mode + { "G90", DRILL_G_ZEROSET, 0 }, // Absolute Mode + { "G00", DRILL_G_ROUT, 1 }, // Route Mode + { "G05", DRILL_G_DRILL, 0 }, // Drill Mode + { "G85", DRILL_G_SLOT, 0 }, // Drill Mode slot (oval holes) + { "G01", DRILL_G_LINEARMOVE, 0 }, // Linear (Straight Line) Mode + { "G02", DRILL_G_CWMOVE, 0 }, // Circular CW Mode + { "G03", DRILL_G_CCWMOVE, 0 }, // Circular CCW Mode + { "G93", DRILL_G_ZERO_SET, 1 }, // Zero Set (XnnYmm and coordintes origin) + { "", DRILL_G_UNKNOWN, 0 }, // last item in list +}; + + +/* + * Read a EXCELLON file. + * Gerber classes are used because there is likeness between Gerber files + * and Excellon files + * DCode can easily store T code (tool size) as round (or oval) shape + * Drill commands are similar to flashed gerber items + * Routing commands are similar to Gerber polygons + * coordinates have the same format as Gerber, can be given in: + * decimal format (i.i. floating notation format) + * integer 2.4 format in imperial units, + * integer 3.2 or 3.3 format (metric units). + */ +bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName ) +{ + wxString msg; + int layerId = getActiveLayer(); // current layer used in GerbView + EXCELLON_IMAGE* drill_Layer = (EXCELLON_IMAGE*) g_GERBER_List.GetGbrImage( layerId ); + + if( drill_Layer == NULL ) + { + drill_Layer = new EXCELLON_IMAGE( this, layerId ); + layerId = g_GERBER_List.AddGbrImage( drill_Layer, layerId ); + } + + if( layerId < 0 ) + { + DisplayError( this, _( "No room to load file" ) ); + return false; + } + + ClearMessageList(); + + /* Read the gerber file */ + FILE * file = wxFopen( aFullFileName, wxT( "rt" ) ); + if( file == NULL ) + { + msg.Printf( _( "File %s not found" ), GetChars( aFullFileName ) ); + DisplayError( this, msg ); + return false; + } + + wxString path = wxPathOnly( aFullFileName ); + + if( path != wxEmptyString ) + wxSetWorkingDirectory( path ); + + bool success = drill_Layer->Read_EXCELLON_File( file, aFullFileName ); + + // Display errors list + if( m_Messages.size() > 0 ) + { + HTML_MESSAGE_BOX dlg( this, _( "Files not found" ) ); + dlg.ListSet( m_Messages ); + dlg.ShowModal(); + } + return success; +} + +bool EXCELLON_IMAGE::Read_EXCELLON_File( FILE * aFile, + const wxString & aFullFileName ) +{ + /* Set the gerber scale: */ + ResetDefaultValues(); + + m_FileName = aFullFileName; + m_Current_File = aFile; + + LOCALE_IO toggleIo; + + // FILE_LINE_READER will close the file. + if( m_Current_File == NULL ) + { + wxMessageBox( wxT("NULL!"), m_FileName ); + return false; + } + + FILE_LINE_READER excellonReader( m_Current_File, m_FileName ); + while( true ) + { + if( excellonReader.ReadLine() == 0 ) + break; + + char* line = excellonReader.Line(); + char* text = StrPurge( line ); + + if( *text == ';' ) // comment: skip line + continue; + + if( m_State == EXCELLON_IMAGE::READ_HEADER_STATE ) + { + Execute_HEADER_Command( text ); + } + else + { + switch( *text ) + { + case 'M': + Execute_HEADER_Command( text ); + break; + + case 'G': /* Line type Gxx : command */ + Execute_EXCELLON_G_Command( text ); + break; + + case 'X': + case 'Y': // command like X12550Y19250 + Execute_Drill_Command(text); + break; + + case 'I': + case 'J': /* Auxiliary Move command */ + m_IJPos = ReadIJCoord( text ); + if( *text == '*' ) // command like X35142Y15945J504 + { + Execute_Drill_Command( text); + } + break; + + case 'T': // Tool command + Select_Tool( text ); + break; + + case '%': + break; + + default: + { + wxString msg; + msg.Printf( wxT( "Unexpected symbol <%c>" ), *text ); + if( GetParent() ) + GetParent()->ReportMessage( msg ); + } + break; + } // End switch + } + } + + // Add our file attribute, to identify the drill file + X2_ATTRIBUTE dummy; + char* text = (char*)file_attribute; + dummy.ParseAttribCmd( m_Current_File, NULL, 0, text ); + delete m_FileFunction; + m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy ); + + m_InUse = true; + + return true; +} + + +bool EXCELLON_IMAGE::Execute_HEADER_Command( char*& text ) +{ + EXCELLON_CMD* cmd = NULL; + int iprm; + double dprm; + D_CODE* dcode; + wxString msg; + + // Search command in list + EXCELLON_CMD* candidate; + + for( unsigned ii = 0; ; ii++ ) + { + candidate = &excellonHeaderCmdList[ii]; + int len = candidate->m_Name.size(); + if( len == 0 ) // End of list reached + break; + if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found. + { + cmd = candidate; + text += len; + break; + } + } + + if( !cmd ) + { + msg.Printf( wxT( "Unknown Excellon command <%s>" ), text ); + ReportMessage( msg ); + while( *text ) + text++; + + return false; + } + + // Execute command + // some do nothing + switch( cmd->m_Code ) + { + case DRILL_SKIP: + case DRILL_M_UNKNOWN: + break; + + case DRILL_M_END: + break; + + case DRILL_M_ENDREWIND: + break; + + case DRILL_M_MESSAGE: + break; + + case DRILL_M_LONGMESSAGE: + break; + + case DRILL_M_HEADER: + m_State = READ_HEADER_STATE; + break; + + case DRILL_M_ENDHEADER: + m_State = READ_PROGRAM_STATE; + break; + + case DRILL_REWIND_STOP: // End of header. No action in a viewer + m_State = READ_PROGRAM_STATE; + break; + + case DRILL_M_METRIC: + SelectUnits( true ); + break; + + case DRILL_METRICHEADER: // command like METRIC,TZ or METRIC,LZ + SelectUnits( true ); + if( *text != ',' ) + { + ReportMessage( _( "METRIC command has no parameter" ) ); + break; + } + text++; // skip separator + if( *text == 'T' ) + m_NoTrailingZeros = false; + else + m_NoTrailingZeros = true; + break; + + case DRILL_M_IMPERIAL: + SelectUnits( false ); + break; + + case DRILL_IMPERIALHEADER: // command like INCH,TZ or INCH,LZ + SelectUnits( false ); + if( *text != ',' ) + { + ReportMessage( _( "INCH command has no parameter" ) ); + break; + } + text++; // skip separator + if( *text == 'T' ) + m_NoTrailingZeros = false; + else + m_NoTrailingZeros = true; + break; + + case DRILL_M_BEGINPATTERN: + break; + + case DRILL_M_ENDPATTERN: + break; + + case DRILL_M_CANNEDTEXT: + break; + + case DRILL_M_TIPCHECK: + break; + + case DRILL_DETECT_BROKEN: + break; + + case DRILL_INCREMENTALHEADER: + if( *text != ',' ) + { + ReportMessage( _( "ICI command has no parameter" ) ); + break; + } + text++; // skip separator + // Parameter should be ON or OFF + if( strnicmp( text, "OFF", 3 ) == 0 ) + m_Relative = false; + else if( strnicmp( text, "ON", 2 ) == 0 ) + m_Relative = true; + else + ReportMessage( _( "ICI command has incorrect parameter" ) ); + break; + + case DRILL_TOOL_CHANGE_STOP: + break; + + case DRILL_AUTOMATIC_SPEED: + break; + + case DRILL_AXIS_VERSION: + break; + + case DRILL_RESET_CMD: + break; + + case DRILL_AUTOMATIC_TOOL_CHANGE: + break; + + case DRILL_FMT: + break; + + case DRILL_TOOL_INFORMATION: + + // Read a tool definition like T1C0.02: + // or T1F00S00C0.02 or T1C0.02F00S00 + // Read tool number: + iprm = ReadInt( text, false ); + + // Skip Feed rate and Spindle speed, if any here + while( *text && ( *text == 'F' || *text == 'S' ) ) + { + text++; + ReadInt( text, false ); + } + + // Read tool shape + if( *text != 'C' ) + ReportMessage( wxString:: Format( + _( "Tool definition <%c> not supported" ), *text ) ); + if( *text ) + text++; + + //read tool diameter: + dprm = ReadDouble( text, false ); + m_Has_DCode = true; + + // Initialize Dcode to handle this Tool + dcode = GetDCODE( iprm + FIRST_DCODE ); // Remember: dcodes are >= FIRST_DCODE + if( dcode == NULL ) + break; + // conv_scale = scaling factor from inch to Internal Unit + double conv_scale = IU_PER_MILS * 1000; + if( m_GerbMetric ) + conv_scale /= 25.4; + + dcode->m_Size.x = dcode->m_Size.y = KiROUND( dprm * conv_scale ); + dcode->m_Shape = APT_CIRCLE; + break; + } + + while( *text ) + text++; + + return true; +} + + +bool EXCELLON_IMAGE::Execute_Drill_Command( char*& text ) +{ + D_CODE* tool; + GERBER_DRAW_ITEM * gbritem; + while( true ) + { + switch( *text ) + { + case 'X': + ReadXYCoord( text ); + break; + case 'Y': + ReadXYCoord( text ); + break; + case 'G': // G85 is found here for oval holes + m_PreviousPos = m_CurrentPos; + Execute_EXCELLON_G_Command( text ); + break; + case 0: // E.O.L: execute command + tool = GetDCODE( m_Current_Tool, false ); + if( !tool ) + { + wxString msg; + msg.Printf( _( "Tool <%d> not defined" ), m_Current_Tool ); + ReportMessage( msg ); + return false; + } + gbritem = new GERBER_DRAW_ITEM( GetParent()->GetGerberLayout(), this ); + GetParent()->GetGerberLayout()->m_Drawings.Append( gbritem ); + if( m_SlotOn ) // Oblong hole + { + fillLineGBRITEM( gbritem, + tool->m_Num_Dcode, GetParent()->getActiveLayer(), + m_PreviousPos, m_CurrentPos, + tool->m_Size, false ); + // the hole is made: reset the slot on command (G85) + // (it is needed for each oblong hole) + m_SlotOn = false; + } + else + { + fillFlashedGBRITEM( gbritem, tool->m_Shape, + tool->m_Num_Dcode, GetParent()->getActiveLayer(), + m_CurrentPos, + tool->m_Size, false ); + } + StepAndRepeatItem( *gbritem ); + m_PreviousPos = m_CurrentPos; + return true; + break; + + default: + text++; + break; + } + } + + return true; +} + + +bool EXCELLON_IMAGE::Select_Tool( char*& text ) +{ + int tool_id = TCodeNumber( text ); + + if( tool_id >= 0 ) + { + tool_id += FIRST_DCODE; // Remember: dcodes are >= FIRST_DCODE + if( tool_id > (TOOLS_MAX_COUNT - 1) ) + tool_id = TOOLS_MAX_COUNT - 1; + m_Current_Tool = tool_id; + D_CODE* pt_Dcode = GetDCODE( tool_id , false ); + if( pt_Dcode ) + pt_Dcode->m_InUse = true; + } + while( *text ) + text++; + + return tool_id >= 0; +} + + +bool EXCELLON_IMAGE::Execute_EXCELLON_G_Command( char*& text ) +{ + EXCELLON_CMD* cmd = NULL; + bool success = false; + int id = DRILL_G_UNKNOWN; + + // Search command in list + EXCELLON_CMD* candidate; + char * gcmd = text; // gcmd points the G command, for error messages. + + for( unsigned ii = 0; ; ii++ ) + { + candidate = &excellon_G_CmdList[ii]; + int len = candidate->m_Name.size(); + if( len == 0 ) // End of list reached + break; + if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found. + { + cmd = candidate; + text += len; + success = true; + id = cmd->m_Code; + break; + } + } + + switch( id ) + { + case DRILL_G_ZERO_SET: + ReadXYCoord( text ); + m_Offset = m_CurrentPos; + break; + + case DRILL_G_ROUT: + m_SlotOn = false; + m_PolygonFillMode = true; + break; + + case DRILL_G_DRILL: + m_SlotOn = false; + m_PolygonFillMode = false; + break; + + case DRILL_G_SLOT: + m_SlotOn = true; + break; + + case DRILL_G_LINEARMOVE: + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; + break; + + case DRILL_G_CWMOVE: + m_Iterpolation = GERB_INTERPOL_ARC_NEG; + break; + + case DRILL_G_CCWMOVE: + m_Iterpolation = GERB_INTERPOL_ARC_POS; + break; + + case DRILL_G_ABSOLUTE: + m_Relative = false; // false = absolute coord + break; + + case DRILL_G_INCREMENTAL: + m_Relative = true; // true = relative coord + break; + + case DRILL_G_UNKNOWN: + default: + { + wxString msg; + msg.Printf( _( "Unknown Excellon G Code: <%s>" ), GetChars(FROM_UTF8(gcmd)) ); + ReportMessage( msg ); + while( *text ) + text++; + return false; + } + } + return success; +} + +void EXCELLON_IMAGE::SelectUnits( bool aMetric ) +{ + /* Coordinates are measured either in inch or metric (millimeters). + * Inch coordinates are in six digits (00.0000) with increments + * as small as 0.0001 (1/10,000). + * Metric coordinates can be measured in microns (thousandths of a millimeter) + * in one of the following three ways: + * Five digit 10 micron resolution (000.00) + * Six digit 10 micron resolution (0000.00) + * Six digit micron resolution (000.000) + */ + /* Inches: Default fmt = 2.4 for X and Y axis: 6 digits with 0.0001 resolution + * metric: Default fmt = 3.3 for X and Y axis: 6 digits, 1 micron resolution + */ + if( aMetric ) + { + m_GerbMetric = true; + // number of digits in mantissa + m_FmtScale.x = m_FmtScale.y = fmtMantissaMM; + // number of digits (mantissa+interger) + 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; + } +} diff --git a/gerbview/export_to_pcbnew.cpp b/gerbview/export_to_pcbnew.cpp new file mode 100644 index 0000000..1b4de9f --- /dev/null +++ b/gerbview/export_to_pcbnew.cpp @@ -0,0 +1,495 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2015 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file export_to_pcbnew.cpp + * @brief Export the layers to Pcbnew. + */ + +#include <vector> + +#include <fctsys.h> +#include <common.h> +#include <confirm.h> +#include <macros.h> +#include <kicad_string.h> +#include <gestfich.h> +#include <trigo.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> +#include <select_layers_to_pcb.h> +#include <build_version.h> +#include <wildcards_and_files_ext.h> + + +// Imported function +extern const wxString GetPCBDefaultLayerName( LAYER_NUM aLayerNumber ); + +#define TO_PCB_UNIT( x ) ( x / IU_PER_MM) + +#define TRACK_TYPE 0 + +/* A helper class to export a Gerber set of files to Pcbnew + */ +class GBR_TO_PCB_EXPORTER +{ +private: + GERBVIEW_FRAME* m_gerbview_frame; // the main gerber frame + wxString m_pcb_file_name; // BOARD file to write to + FILE* m_fp; // the board file + int m_pcbCopperLayersCount; + std::vector<wxPoint> m_vias_coordinates; // list of already generated vias, + // used to export only once a via + // having a given coordinate +public: + GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME* aFrame, const wxString& aFileName ); + ~GBR_TO_PCB_EXPORTER(); + + /** + * Function ExportPcb + * saves a board from a set of Gerber images. + */ + bool ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLayers ); + +private: + /** + * Function export_non_copper_item + * write a non copper line or arc to the board file. + * @param aGbrItem = the Gerber item (line, arc) to export + * @param aLayer = the technical layer to use + */ + void export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ); + + /** + * Function export_copper_item + * write a track or via) to the board file. + * @param aGbrItem = the Gerber item (line, arc, flashed) to export + * @param aLayer = the copper layer to use + */ + void export_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ); + + /** + * Function export_flashed_copper_item + * write a via to the board file (always uses a via through). + * @param aGbrItem = the flashed Gerber item to export + */ + void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem ); + + /** + * Function export_segline_copper_item + * write a track (not via) to the board file. + * @param aGbrItem = the Gerber item (line only) to export + * @param aLayer = the copper layer to use + */ + void export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ); + + /** + * Function export_segarc_copper_item + * write a set of tracks (arcs are approximated by track segments) + * to the board file. + * @param aGbrItem = the Gerber item (arc only) to export + * @param aLayer = the copper layer to use + */ + void export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ); + + /** + * function writePcbLineItem + * basic write function to write a DRAWSEGMENT item or a TRACK item + * to the board file, from a non flashed item + */ + void writePcbLineItem( bool aIsArc, wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer, double aAngle = 0 ); + + /** + * function writeCopperLineItem + * basic write function to write a a TRACK item + * to the board file, from a non flashed item + */ + void writeCopperLineItem( wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer ); + + /** + * function writePcbHeader + * Write a very basic header to the board file + */ + void writePcbHeader( LAYER_NUM* aLayerLookUpTable ); +}; + + +GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME* aFrame, const wxString& aFileName ) +{ + m_gerbview_frame = aFrame; + m_pcb_file_name = aFileName; + m_fp = NULL; + m_pcbCopperLayersCount = 2; +} + + +GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER() +{ +} + + +/* Export data in Pcbnew format + * remember Pcbnew uses a Y reversed axis, so we must negate all Y coordinates + */ +void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) +{ + int layercount = 0; + + // Count the Gerber layers which are actually currently used + for( LAYER_NUM ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + if( g_GERBER_List.GetGbrImage( ii ) ) + layercount++; + } + + if( layercount == 0 ) + { + DisplayInfoMessage( this, + _( "None of the Gerber layers contain any data" ) ); + return; + } + + wxString fileName; + wxString path = m_mruPath; + + wxFileDialog filedlg( this, _( "Board file name:" ), + path, fileName, PcbFileWildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); + + if( filedlg.ShowModal() == wxID_CANCEL ) + return; + + fileName = filedlg.GetPath(); + + /* Install a dialog frame to choose the mapping + * between gerber layers and Pcbnew layers + */ + LAYERS_MAP_DIALOG* layerdlg = new LAYERS_MAP_DIALOG( this ); + int ok = layerdlg->ShowModal(); + layerdlg->Destroy(); + + if( ok != wxID_OK ) + return; + + m_mruPath = wxFileName( fileName ).GetPath(); + + GBR_TO_PCB_EXPORTER gbr_exporter( this, fileName ); + + gbr_exporter.ExportPcb( layerdlg->GetLayersLookUpTable(), layerdlg->GetCopperLayersCount() ); +} + + +bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLayers ) +{ + LOCALE_IO toggle; // toggles on, then off, the C locale. + + m_fp = wxFopen( m_pcb_file_name, wxT( "wt" ) ); + + if( m_fp == NULL ) + { + wxString msg; + msg.Printf( _( "Cannot create file '%s'" ), GetChars( m_pcb_file_name ) ); + DisplayError( m_gerbview_frame, msg ); + return false; + } + + m_pcbCopperLayersCount = aCopperLayers; + + writePcbHeader( aLayerLookUpTable ); + + // create an image of gerber data + // First: non copper layers: + GERBER_DRAW_ITEM* gerb_item = m_gerbview_frame->GetItemsList(); + int pcbCopperLayerMax = 31; + + for( ; gerb_item; gerb_item = gerb_item->Next() ) + { + int layer = gerb_item->GetLayer(); + LAYER_NUM pcb_layer_number = aLayerLookUpTable[layer]; + + if( !IsPcbLayer( pcb_layer_number ) ) + continue; + + if( pcb_layer_number > pcbCopperLayerMax ) + export_non_copper_item( gerb_item, pcb_layer_number ); + } + + // Copper layers + gerb_item = m_gerbview_frame->GetItemsList(); + + for( ; gerb_item; gerb_item = gerb_item->Next() ) + { + int layer = gerb_item->GetLayer(); + LAYER_NUM pcb_layer_number = aLayerLookUpTable[layer]; + + if( pcb_layer_number < 0 || pcb_layer_number > pcbCopperLayerMax ) + continue; + + else + export_copper_item( gerb_item, pcb_layer_number ); + } + + fprintf( m_fp, ")\n" ); + + fclose( m_fp ); + m_fp = NULL; + return true; +} + + +void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ) +{ + bool isArc = false; + + double angle = 0; + wxPoint seg_start = aGbrItem->m_Start; + wxPoint seg_end = aGbrItem->m_End; + + if( aGbrItem->m_Shape == GBR_ARC ) + { + double a = atan2( (double) ( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y), + (double) ( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); + double b = atan2( (double) ( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), + (double) ( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); + + isArc = true; + angle = RAD2DEG(b - a); + seg_start = aGbrItem->m_ArcCentre; + + // Ensure arc orientation is CCW + if( angle < 0 ) + angle += 360.0; + } + + // Reverse Y axis: + seg_start.y = -seg_start.y; + seg_end.y = -seg_end.y; + writePcbLineItem( isArc, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, angle ); +} + + +void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ) +{ + switch( aGbrItem->m_Shape ) + { + case GBR_SPOT_CIRCLE: + case GBR_SPOT_RECT: + case GBR_SPOT_OVAL: + // replace spots with vias when possible + export_flashed_copper_item( aGbrItem ); + break; + + case GBR_ARC: + export_segarc_copper_item( aGbrItem, aLayer ); + break; + + default: + export_segline_copper_item( aGbrItem, aLayer ); + break; + } +} + + +void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ) +{ + wxPoint seg_start, seg_end; + + seg_start = aGbrItem->m_Start; + seg_end = aGbrItem->m_End; + + // Reverse Y axis: + seg_start.y = -seg_start.y; + seg_end.y = -seg_end.y; + + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); +} + + +void GBR_TO_PCB_EXPORTER::writeCopperLineItem( wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer ) +{ + fprintf( m_fp, "(segment (start %s %s) (end %s %s) (width %s) (layer %s) (net 0))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ) ); +} + + +void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ) +{ + double a = atan2( (double) ( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y ), + (double) ( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); + double b = atan2( (double) ( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), + (double) ( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); + + wxPoint start = aGbrItem->m_Start; + wxPoint end = aGbrItem->m_End; + + /* Because Pcbnew does not know arcs in tracks, + * approximate arc by segments (SEG_COUNT__CIRCLE segment per 360 deg) + * The arc is drawn anticlockwise from the start point to the end point. + */ + #define SEG_COUNT_CIRCLE 16 + #define DELTA_ANGLE 2 * M_PI / SEG_COUNT_CIRCLE + + // calculate the number of segments from a to b. + // we want CNT_PER_360 segments fo a circle + if( a > b ) + b += 2 * M_PI; + + wxPoint curr_start = start; + wxPoint seg_start, seg_end; + + int ii = 1; + + for( double rot = a; rot < (b - DELTA_ANGLE); rot += DELTA_ANGLE, ii++ ) + { + seg_start = curr_start; + wxPoint curr_end = start; + RotatePoint( &curr_end, aGbrItem->m_ArcCentre, + -RAD2DECIDEG( DELTA_ANGLE * ii ) ); + seg_end = curr_end; + // Reverse Y axis: + seg_start.y = -seg_start.y; + seg_end.y = -seg_end.y; + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); + curr_start = curr_end; + } + + if( end != curr_start ) + { + seg_start = curr_start; + seg_end = end; + // Reverse Y axis: + seg_start.y = -seg_start.y; + seg_end.y = -seg_end.y; + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); + } +} + + +/* + * creates a via from a flashed gerber item. + * Flashed items are usually pads or vias, so we try to export all of them + * using vias + */ +void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem ) +{ + // First, explore already created vias, before creating a new via + for( unsigned ii = 0; ii < m_vias_coordinates.size(); ii++ ) + { + if( m_vias_coordinates[ii] == aGbrItem->m_Start ) // Already created + return; + } + + m_vias_coordinates.push_back( aGbrItem->m_Start ); + + wxPoint via_pos = aGbrItem->m_Start; + int width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; + // Reverse Y axis: + via_pos.y = -via_pos.y; + + // Layers are Front to Back + fprintf( m_fp, " (via (at %s %s) (size %s)", + Double2Str( TO_PCB_UNIT(via_pos.x) ).c_str(), + Double2Str( TO_PCB_UNIT(via_pos.y) ).c_str(), + Double2Str( TO_PCB_UNIT( width ) ).c_str() ); + + fprintf( m_fp, " (layers %s %s))\n", + TO_UTF8( GetPCBDefaultLayerName( F_Cu ) ), + TO_UTF8( GetPCBDefaultLayerName( B_Cu ) ) ); +} + +void GBR_TO_PCB_EXPORTER::writePcbHeader( LAYER_NUM* aLayerLookUpTable ) +{ + fprintf( m_fp, "(kicad_pcb (version 4) (host Gerbview \"%s\")\n\n", + TO_UTF8( GetBuildVersion() ) ); + + // Write layers section + fprintf( m_fp, " (layers \n" ); + + for( int ii = 0; ii < m_pcbCopperLayersCount; ii++ ) + { + int id = ii; + + if( ii == m_pcbCopperLayersCount-1) + id = B_Cu; + + fprintf( m_fp, " (%d %s signal)\n", id, TO_UTF8( GetPCBDefaultLayerName( id ) ) ); + } + + for( int ii = B_Adhes; ii < LAYER_ID_COUNT; ii++ ) + { + fprintf( m_fp, " (%d %s user)\n", ii, TO_UTF8( GetPCBDefaultLayerName( ii ) ) ); + } + + fprintf( m_fp, " )\n\n" ); +} + + +void GBR_TO_PCB_EXPORTER::writePcbLineItem( bool aIsArc, wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer, double aAngle ) +{ + if( aIsArc && ( aAngle == 360.0 || aAngle == 0 ) ) + { + fprintf( m_fp, "(gr_circle (center %s %s) (end %s %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } + else if( aIsArc ) + { + fprintf( m_fp, "(gr_arc (start %s %s) (end %s %s) (angle %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + Double2Str( aAngle ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } + else + { + fprintf( m_fp, "(gr_line (start %s %s) (end %s %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } +} diff --git a/gerbview/files.cpp b/gerbview/files.cpp new file mode 100644 index 0000000..2bf2ef1 --- /dev/null +++ b/gerbview/files.cpp @@ -0,0 +1,303 @@ +/** + * @file gerbview/files.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <gestfich.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <gerbview_id.h> +#include <class_gerbview_layer_widget.h> +#include <wildcards_and_files_ext.h> + + +void GERBVIEW_FRAME::OnGbrFileHistory( wxCommandEvent& event ) +{ + wxString fn; + + fn = GetFileFromHistory( event.GetId(), _( "Gerber files" ) ); + + if( !fn.IsEmpty() ) + { + Erase_Current_DrawLayer( false ); + LoadGerberFiles( fn ); + } +} + + +void GERBVIEW_FRAME::OnDrlFileHistory( wxCommandEvent& event ) +{ + wxString fn; + + fn = GetFileFromHistory( event.GetId(), _( "Drill files" ), &m_drillFileHistory ); + + if( !fn.IsEmpty() ) + { + Erase_Current_DrawLayer( false ); + LoadExcellonFiles( fn ); + } +} + + +/* File commands. */ +void GERBVIEW_FRAME::Files_io( wxCommandEvent& event ) +{ + int id = event.GetId(); + + switch( id ) + { + case wxID_FILE: + Erase_Current_DrawLayer( false ); + LoadGerberFiles( wxEmptyString ); + break; + + case ID_GERBVIEW_ERASE_ALL: + Clear_DrawLayers( false ); + Zoom_Automatique( false ); + m_canvas->Refresh(); + ClearMsgPanel(); + ReFillLayerWidget(); + break; + + case ID_GERBVIEW_LOAD_DRILL_FILE: + LoadExcellonFiles( wxEmptyString ); + m_canvas->Refresh(); + break; + + default: + wxFAIL_MSG( wxT( "File_io: unexpected command id" ) ); + break; + } +} + + +bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) +{ + wxString filetypes; + wxArrayString filenamesList; + wxFileName filename = aFullFileName; + wxString currentPath; + + if( !filename.IsOk() ) + { + /* Standard gerber filetypes + * (See http://en.wikipedia.org/wiki/Gerber_File) + * the .gbr (.pho in legacy files) extension is the default used in Pcbnew + * However there are a lot of other extensions used for gerber files + * Because the first letter is usually g, we accept g* as extension + * (Mainly internal copper layers do not have specific extension, + * and filenames are like *.g1, *.g2 *.gb1 ...). + * Now (2014) Ucamco (the company which manager the Gerber format) encourage + * use of .gbr only and the Gerber X2 file format. + */ + filetypes = _( "Gerber files (.g* .lgr .pho)" ); + filetypes << wxT("|"); + filetypes += wxT("*.g*;*.G*;*.pho;*.PHO" ); + filetypes << wxT("|"); + + /* Special gerber filetypes */ + filetypes += _( "Top layer (*.GTL)|*.GTL;*.gtl|" ); + filetypes += _( "Bottom layer (*.GBL)|*.GBL;*.gbl|" ); + filetypes += _( "Bottom solder resist (*.GBS)|*.GBS;*.gbs|" ); + filetypes += _( "Top solder resist (*.GTS)|*.GTS;*.gts|" ); + filetypes += _( "Bottom overlay (*.GBO)|*.GBO;*.gbo|" ); + filetypes += _( "Top overlay (*.GTO)|*.GTO;*.gto|" ); + filetypes += _( "Bottom paste (*.GBP)|*.GBP;*.gbp|" ); + filetypes += _( "Top paste (*.GTP)|*.GTP;*.gtp|" ); + filetypes += _( "Keep-out layer (*.GKO)|*.GKO;*.gko|" ); + filetypes += _( "Mechanical layers (*.GMx)|*.GM1;*.gm1;*.GM2;*.gm2;*.GM3;*.gm3|" ); + filetypes += _( "Top Pad Master (*.GPT)|*.GPT;*.gpt|" ); + filetypes += _( "Bottom Pad Master (*.GPB)|*.GPB;*.gpb|" ); + + /* All filetypes */ + filetypes += AllFilesWildcard; + + /* Use the current working directory if the file name path does not exist. */ + if( filename.DirExists() ) + currentPath = filename.GetPath(); + else + currentPath = m_mruPath; + + wxFileDialog dlg( this, + _( "Open Gerber File" ), + currentPath, + filename.GetFullName(), + filetypes, + wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return false; + + dlg.GetPaths( filenamesList ); + + // @todo Take a closer look at the CWD switching here. The current working directory + // gets changed by wxFileDialog because the wxFD_CHANGE_DIR flag is set. Is this the + // appropriate behavior? The current working directory is not returned to the previous + // value so this may be an issue elsewhere. + currentPath = wxGetCwd(); + m_mruPath = currentPath; + } + else + { + wxFileName filename = aFullFileName; + filenamesList.Add( aFullFileName ); + currentPath = filename.GetPath(); + m_mruPath = currentPath; + } + + // Read gerber files: each file is loaded on a new GerbView layer + int layer = getActiveLayer(); + + for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) + { + wxFileName filename = filenamesList[ii]; + + if( !filename.IsAbsolute() ) + filename.SetPath( currentPath ); + + m_lastFileName = filename.GetFullPath(); + + setActiveLayer( layer, false ); + + if( Read_GERBER_File( filename.GetFullPath(), filename.GetFullPath() ) ) + { + UpdateFileHistory( m_lastFileName ); + + layer = getNextAvailableLayer( layer ); + + if( layer == NO_AVAILABLE_LAYERS ) + { + wxString msg = wxT( "No more empty available layers.\n" + "The remaining gerber files will not be loaded." ); + wxMessageBox( msg ); + break; + } + + setActiveLayer( layer, false ); + } + } + + Zoom_Automatique( false ); + + // Synchronize layers tools with actual active layer: + ReFillLayerWidget(); + setActiveLayer( getActiveLayer() ); + m_LayersManager->UpdateLayerIcons(); + syncLayerBox(); + return true; +} + + +bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) +{ + wxString filetypes; + wxArrayString filenamesList; + wxFileName filename = aFullFileName; + wxString currentPath; + + if( !filename.IsOk() ) + { + filetypes = wxGetTranslation( DrillFileWildcard ); + filetypes << wxT("|"); + /* All filetypes */ + filetypes += wxGetTranslation( AllFilesWildcard ); + + /* Use the current working directory if the file name path does not exist. */ + if( filename.DirExists() ) + currentPath = filename.GetPath(); + else + currentPath = m_mruPath; + + wxFileDialog dlg( this, + _( "Open Drill File" ), + currentPath, + filename.GetFullName(), + filetypes, + wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE | wxFD_CHANGE_DIR ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return false; + + dlg.GetPaths( filenamesList ); + currentPath = wxGetCwd(); + m_mruPath = currentPath; + } + else + { + wxFileName filename = aFullFileName; + filenamesList.Add( aFullFileName ); + currentPath = filename.GetPath(); + m_mruPath = currentPath; + } + + // Read gerber files: each file is loaded on a new GerbView layer + int layer = getActiveLayer(); + + for( unsigned ii = 0; ii < filenamesList.GetCount(); ii++ ) + { + wxFileName filename = filenamesList[ii]; + + if( !filename.IsAbsolute() ) + filename.SetPath( currentPath ); + + m_lastFileName = filename.GetFullPath(); + + setActiveLayer( layer, false ); + + if( Read_EXCELLON_File( filename.GetFullPath() ) ) + { + // Update the list of recent drill files. + UpdateFileHistory( filename.GetFullPath(), &m_drillFileHistory ); + + layer = getNextAvailableLayer( layer ); + + if( layer == NO_AVAILABLE_LAYERS ) + { + wxString msg = wxT( "No more empty available layers.\n" + "The remaining gerber files will not be loaded." ); + wxMessageBox( msg ); + break; + } + + setActiveLayer( layer, false ); + } + } + + Zoom_Automatique( false ); + + // Synchronize layers tools with actual active layer: + ReFillLayerWidget(); + setActiveLayer( getActiveLayer() ); + m_LayersManager->UpdateLayerIcons(); + syncLayerBox(); + + return true; +} diff --git a/gerbview/gerber_test_files/aperture-circle-flash-with_hole.gbr b/gerbview/gerber_test_files/aperture-circle-flash-with_hole.gbr new file mode 100644 index 0000000..8ae16ce --- /dev/null +++ b/gerbview/gerber_test_files/aperture-circle-flash-with_hole.gbr @@ -0,0 +1,27 @@ +G04 Test flashing of circular apertures* +G04 Four groups of circular apertures are arranged in a square* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ADD10C,0.050*% +%ADD11C,0.050X0.025*% +%ADD12C,0.050X0.025X0.030*% + +G04 No hole, centered at 0,0 * +G54D10* +X0Y0D03* + +G04 Round hole, centered at 0.1,0 * +G54D11* +X00100Y0D03* + +G04 Square hole, centered at 0,0.1 * +G54D12* +X0Y00100D03* + +G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 * +G54D11* +X100Y90D03* +X00100Y00110D03* + +M02* diff --git a/gerbview/gerber_test_files/aperture-obround-flash-with_hole.gbr b/gerbview/gerber_test_files/aperture-obround-flash-with_hole.gbr new file mode 100644 index 0000000..b09bf43 --- /dev/null +++ b/gerbview/gerber_test_files/aperture-obround-flash-with_hole.gbr @@ -0,0 +1,27 @@ +G04 Test flashing of obround apertures* +G04 Four groups of obround apertures are arranged in a square* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ADD10O,0.050X0.080*% +%ADD11O,0.080X0.050X0.025*% +%ADD12O,0.050X0.025X0.025X0.0150*% + +G04 No hole, centered at 0,0 * +G54D10* +X0Y0D03* + +G04 Round hole, centered at 0.1,0 * +G54D11* +X00100Y0D03* + +G04 Square hole, centered at 0,0.1 * +G54D12* +X0Y00100D03* + +G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 * +G54D11* +X00100Y00090D03* +X00100Y00110D03* + +M02* diff --git a/gerbview/gerber_test_files/aperture_macro-no_param-test.gbr b/gerbview/gerber_test_files/aperture_macro-no_param-test.gbr new file mode 100644 index 0000000..f586dbe --- /dev/null +++ b/gerbview/gerber_test_files/aperture_macro-no_param-test.gbr @@ -0,0 +1,82 @@ +G04 Verification of all aperture macros * +G04 Handcoded by Stefan Petersen * +%MOIN*% +%FSLAX23Y23*% +%OFA0.0000B0.0000*% +G90* +%AMCIRCLE* +1,1,0.5,0,0* +% +%AMVECTOR* +2,1,0.3,0,0,1,1,-15* +% +%AMLINE* +21,1,0.3,0.05,0,0,-135* +% +%AMLINE2* +22,1,0.8,0.5,0,0,-45* +% +%AMOUTLINE* +4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25* +% +%AMPOLYGON* +5,1,5,0,0,0.5,25* +% +%AMMOIRE* +6,0,0,1.0,0.1,0.4,2,0.01,1,20* +% +%AMTHERMAL* +7,0,0,1.0,0.3,0.04,-13* +% +%ADD10C,0.0650*% +%ADD11CIRCLE*% +%ADD12VECTOR*% +%ADD13LINE*% +%ADD14LINE2*% +%ADD15OUTLINE*% +%ADD16POLYGON*% +%ADD18MOIRE*% +%ADD19THERMAL*% +G04 Outline* +X0Y0D02* +G54D10* +X0Y0D01* +X10000D01* +Y10000D01* +X0D01* +Y0D01* +G04 Dots * +X2000Y5000D03* +X3000D03* +X4000D03* +X5000D03* +X6000D03* +X7000D03* +X8000D03* +X9000D03* +Y6200X9000D03* +G04 Draw circle* +G54D11* +X2000Y5000D03* +G04 Draw line vector * +G54D12* +X3000D03* +G04 Draw line center * +G54D13* +X4000D03* +G04 Draw line lower left * +G54D14* +X5000D03* +G04 Draw outline * +G54D15* +X6000D03* +G04 Draw polygon 1 * +G54D16* +X7000D03* +G04 Draw Moire * +G54D18* +X9000D03* +G04 Draw Thermal * +G54D19* +Y6200X9000D03* +M02* diff --git a/gerbview/gerber_test_files/aperture_macro-with_param-test.gbr b/gerbview/gerber_test_files/aperture_macro-with_param-test.gbr new file mode 100644 index 0000000..774d97a --- /dev/null +++ b/gerbview/gerber_test_files/aperture_macro-with_param-test.gbr @@ -0,0 +1,99 @@ +G04 Verification of all aperture macros * +G04 Handcoded by Stefan Petersen * +%MOIN*% +%FSLAX23Y23*% +%OFA0.0000B0.0000*% +G90* +%AMCIRCLE* +1,1,$1,0,0* +% +%AMVECTOR* +2,1,$1,0,0,$2,$3,-135* +% +%AMVECTOR1* +2,1,0.3,0,0,1,1,-15* +% +%AMLINE1* +21,1,$1,$2,0,0,-135* +% +%AMLINE* +21,1,0.3,0.03,0,0,-135* +% +%AMLINE2* +22,1,$1,$2,0,0,-45* +% +%AMLINELOWLEFT* +22,1,0.2,1.5,0,0,-15* +% +%AMOUTLINE* +4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25* +% +%AMPOLYGON* +5,1,$1,0,0,0.5,$2* +% +%AMMOIRE* +6,0,0,1.0,0.1,0.4,2,0.01,1,20* +% +%AMTHERMAL* +7,0,0,1.0,0.3,0.01,-13* +% +%ADD10C,0.0650*% +%ADD11CIRCLE,.5*% +%ADD12VECTOR,0.05X1X0*% +%ADD13LINE1,0.3X0.05*% +%ADD14LINE2,0.8X0.5*% +%ADD15OUTLINE*% +%ADD16POLYGON,3X-10*% +%ADD17POLYGON,6X10*% +%ADD18MOIRE*% +%ADD19THERMAL*% +%ADD20LINELOWLEFT*% +G04 Outline* +X0Y0D02* +G54D10* +X0Y0D01* +X10000D01* +Y10000D01* +X0D01* +Y0D01* +G04 Dots * +X2000Y5000D03* +X3000D03* +X4000D03* +X5000D03* +X6000D03* +X7000D03* +X8000D03* +X9000D03* +Y6200X9000D03* +G04 Draw circle* +G54D11* +X2000Y5000D03* +G04 Draw line vector * +G54D12* +X3000D03* +G04 Draw line center * +G54D13* +X4000D03* +G04 Draw line lower left * +G54D14* +X5000D03* +G04 Draw outline * +G54D15* +X6000D03* +G04 Draw polygon 1 * +G54D16* +X7000D03* +G04 Draw polygon 1 * +G54D17* +X8000D03* +G04 Draw Moire * +G54D18* +X9000D03* +G04 Draw vector at 0,0* +G54D20* +X00000Y00000D03* +G04 Draw Thermal * +G54D19* +Y6200X9000D03* +M02* diff --git a/gerbview/gerber_test_files/apertures_rotated.gbr b/gerbview/gerber_test_files/apertures_rotated.gbr new file mode 100644 index 0000000..3f1e727 --- /dev/null +++ b/gerbview/gerber_test_files/apertures_rotated.gbr @@ -0,0 +1,1109 @@ +%ICAS*% +%FSLAX44Y44*% +%OFA0B0*% +%SFA1B1*% +%MOMM*% +%AMFRECTNOHOLE10* +21,1,1.5748,2.2860,0.0000,0.0000,0* +% +%AMFRECTNOHOLE11* +21,1,0.5080,1.1430,0.0000,0.0000,180* +% +%AMFRECTNOHOLE12* +21,1,1.5240,2.0320,0.0000,0.0000,180* +% +%AMFRECTNOHOLE13* +21,1,1.5240,2.0320,0.0000,0.0000,270* +% +%AMFRECTNOHOLE14* +21,1,1.5240,2.0320,0.0000,0.0000,90* +% +%AMFRECTNOHOLE15* +21,1,0.8890,1.3970,0.0000,0.0000,270* +% +%ADD10FRECTNOHOLE10*% +%ADD11FRECTNOHOLE11*% +%ADD12FRECTNOHOLE12*% +%ADD13FRECTNOHOLE13*% +%ADD14FRECTNOHOLE14*% +%ADD15FRECTNOHOLE15*% +%ADD17C,0.3048X0.0000X0.0000*% +%ADD19C,1.6764X0.0000X0.0000*% +%ADD22C,2.2860X0.0000X0.0000*% +%LNBottom*% +G54D10* +X2279650Y-1339850D3* +X1809750Y-1339850D3* +G54D11* +X2355850Y-1435100D3* +X2343150Y-1371600D3* +X2355850Y-1371600D3* +X2368550Y-1371600D3* +X2381250Y-1371600D3* +X2393950Y-1371600D3* +X2406650Y-1371600D3* +X2419350Y-1371600D3* +X2432050Y-1371600D3* +X2432050Y-1435100D3* +X2419350Y-1435100D3* +X2406650Y-1435100D3* +X2393950Y-1435100D3* +X2381250Y-1435100D3* +X2368550Y-1435100D3* +X2343150Y-1435100D3* +X1885950Y-1435100D3* +X1873250Y-1371600D3* +X1885950Y-1371600D3* +X1898650Y-1371600D3* +X1911350Y-1371600D3* +X1924050Y-1371600D3* +X1936750Y-1371600D3* +X1949450Y-1371600D3* +X1962150Y-1371600D3* +X1962150Y-1435100D3* +X1949450Y-1435100D3* +X1936750Y-1435100D3* +X1924050Y-1435100D3* +X1911350Y-1435100D3* +X1898650Y-1435100D3* +X1873250Y-1435100D3* +G54D12* +X2024380Y-1430020D3* +X1991360Y-1430020D3* +G54D13* +X2272030Y-1418590D3* +X2272030Y-1451610D3* +G54D14* +X2101850Y-1369060D3* +X2101850Y-1336040D3* +X2228850Y-1369060D3* +X2228850Y-1336040D3* +X2190750Y-1369060D3* +X2190750Y-1336040D3* +X2152650Y-1369060D3* +X2152650Y-1336040D3* +G54D15* +X1986280Y-1386205D3* +X1986280Y-1405255D3* +X2321560Y-1384935D3* +X2321560Y-1403985D3* +X2059940Y-1339215D3* +X2059940Y-1358265D3* +G54D17* +X1873250Y-1439291D2* +X1873250Y-1435100D1* +X1873250Y-1441867D2* +X1873250Y-1439291D1* +X1874738Y-1443355D2* +X1873250Y-1441867D1* +X1881450Y-1445546D2* +X1874738Y-1443355D1* +X1883990Y-1445546D2* +X1881450Y-1445546D1* +X1887910Y-1445546D2* +X1883990Y-1445546D1* +X1890068Y-1444625D2* +X1887910Y-1445546D1* +X1892300Y-1442393D2* +X1890068Y-1444625D1* +X1892300Y-1427807D2* +X1892300Y-1442393D1* +X1894532Y-1425575D2* +X1892300Y-1427807D1* +X1896690Y-1424654D2* +X1894532Y-1425575D1* +X1900610Y-1424654D2* +X1896690Y-1424654D1* +X1902768Y-1425575D2* +X1900610Y-1424654D1* +X1905000Y-1427807D2* +X1902768Y-1425575D1* +X1905000Y-1442393D2* +X1905000Y-1427807D1* +X1907232Y-1444625D2* +X1905000Y-1442393D1* +X1909390Y-1445546D2* +X1907232Y-1444625D1* +X1922090Y-1445546D2* +X1909390Y-1445546D1* +X1926010Y-1445546D2* +X1922090Y-1445546D1* +X1928168Y-1444625D2* +X1926010Y-1445546D1* +X1930400Y-1442393D2* +X1928168Y-1444625D1* +X1930400Y-1427807D2* +X1930400Y-1442393D1* +X1932632Y-1425575D2* +X1930400Y-1427807D1* +X1937330Y-1424654D2* +X1932632Y-1425575D1* +X1941250Y-1424654D2* +X1937330Y-1424654D1* +X1948180Y-1424686D2* +X1941250Y-1424654D1* +X1949450Y-1430909D2* +X1949450Y-1435100D1* +X1949450Y-1428333D2* +X1949450Y-1430909D1* +X1948180Y-1424686D2* +X1949450Y-1428333D1* +X2419350Y-1430909D2* +X2419350Y-1435100D1* +X2419350Y-1428333D2* +X2419350Y-1430909D1* +X2417862Y-1426845D2* +X2419350Y-1428333D1* +X2411150Y-1424654D2* +X2417862Y-1426845D1* +X2408610Y-1424654D2* +X2411150Y-1424654D1* +X2404690Y-1424654D2* +X2408610Y-1424654D1* +X2402532Y-1425575D2* +X2404690Y-1424654D1* +X2400300Y-1427807D2* +X2402532Y-1425575D1* +X2400300Y-1447822D2* +X2400300Y-1427807D1* +X2398931Y-1451126D2* +X2400300Y-1447822D1* +X2389021Y-1461036D2* +X2398931Y-1451126D1* +X2385717Y-1462405D2* +X2389021Y-1461036D1* +X2378280Y-1463326D2* +X2385717Y-1462405D1* +X2363900Y-1463326D2* +X2378280Y-1463326D1* +X2358820Y-1463326D2* +X2363900Y-1463326D1* +X2355177Y-1461817D2* +X2358820Y-1463326D1* +X2345008Y-1451648D2* +X2355177Y-1461817D1* +X2343499Y-1448005D2* +X2345008Y-1451648D1* +X2343150Y-1445023D2* +X2343499Y-1448005D1* +X2343150Y-1439291D2* +X2343150Y-1445023D1* +X2343150Y-1435100D2* +X2343150Y-1439291D1* +X2223421Y-1342136D2* +X2228850Y-1336040D1* +X2223421Y-1345620D2* +X2223421Y-1342136D1* +X2223262Y-1348486D2* +X2223421Y-1345620D1* +X2110486Y-1338929D2* +X2101850Y-1336040D1* +X2113970Y-1338929D2* +X2110486Y-1338929D1* +X2140530Y-1348391D2* +X2113970Y-1338929D1* +X2175252Y-1356856D2* +X2140530Y-1348391D1* +X2195572Y-1356856D2* +X2175252Y-1356856D1* +X2206248Y-1356856D2* +X2195572Y-1356856D1* +X2206467Y-1356765D2* +X2206248Y-1356856D1* +X2223262Y-1348486D2* +X2206467Y-1356765D1* +X2093214Y-1338929D2* +X2101850Y-1336040D1* +X2089730Y-1338929D2* +X2093214Y-1338929D1* +X2072640Y-1343914D2* +X2089730Y-1338929D1* +X2057686Y-1361186D2* +X2059940Y-1358265D1* +X2057686Y-1364670D2* +X2057686Y-1361186D1* +X2054915Y-1367441D2* +X2057686Y-1364670D1* +X1999062Y-1404116D2* +X2054915Y-1367441D1* +X1998687Y-1404271D2* +X1999062Y-1404116D1* +X1995106Y-1405255D2* +X1998687Y-1404271D1* +X1991741Y-1405255D2* +X1995106Y-1405255D1* +X1986280Y-1405255D2* +X1991741Y-1405255D1* +X2062194Y-1355344D2* +X2059940Y-1358265D1* +X2062194Y-1351860D2* +X2062194Y-1355344D1* +X2064965Y-1349089D2* +X2062194Y-1351860D1* +X2068885Y-1348391D2* +X2064965Y-1349089D1* +X2071656Y-1345620D2* +X2068885Y-1348391D1* +X2072640Y-1343914D2* +X2071656Y-1345620D1* +X2065401Y-1339215D2* +X2059940Y-1339215D1* +X2068766Y-1339215D2* +X2065401Y-1339215D1* +X2071370Y-1341819D2* +X2068766Y-1339215D1* +X2072640Y-1343914D2* +X2071370Y-1341819D1* +X2316099Y-1403985D2* +X2321560Y-1403985D1* +X2308957Y-1403985D2* +X2316099Y-1403985D1* +X2308220Y-1403680D2* +X2308957Y-1403985D1* +X2303742Y-1401492D2* +X2308220Y-1403680D1* +X2240970Y-1356709D2* +X2303742Y-1401492D1* +X2223262Y-1348486D2* +X2240970Y-1356709D1* +X2323814Y-1406906D2* +X2321560Y-1403985D1* +X2323814Y-1410390D2* +X2323814Y-1406906D1* +X2335879Y-1431345D2* +X2323814Y-1410390D1* +X2338650Y-1434116D2* +X2335879Y-1431345D1* +X2340610Y-1434116D2* +X2338650Y-1434116D1* +X2342134Y-1434116D2* +X2340610Y-1434116D1* +X2343150Y-1435100D2* +X2342134Y-1434116D1* +X1980819Y-1405255D2* +X1986280Y-1405255D1* +X1977454Y-1405255D2* +X1980819Y-1405255D1* +X1948180Y-1424686D2* +X1977454Y-1405255D1* +X2030476Y-1426210D2* +X2024380Y-1430020D1* +X2057095Y-1426210D2* +X2030476Y-1426210D1* +X2057095Y-1422400D2* +X2057095Y-1426210D1* +X2158079Y-1375156D2* +X2152650Y-1369060D1* +X2158079Y-1378640D2* +X2158079Y-1375156D1* +X2162099Y-1416050D2* +X2158079Y-1378640D1* +X2162099Y-1422400D2* +X2162099Y-1416050D1* +X2232101Y-1375156D2* +X2228850Y-1369060D1* +X2232101Y-1416050D2* +X2232101Y-1375156D1* +X2232101Y-1422400D2* +X2232101Y-1416050D1* +X2161286Y-1338929D2* +X2152650Y-1336040D1* +X2164770Y-1338929D2* +X2161286Y-1338929D1* +X2178691Y-1348244D2* +X2164770Y-1338929D1* +X2199011Y-1348244D2* +X2178691Y-1348244D1* +X2202809Y-1348244D2* +X2199011Y-1348244D1* +X2205494Y-1345559D2* +X2202809Y-1348244D1* +X2213959Y-1326460D2* +X2205494Y-1345559D1* +X2216730Y-1323689D2* +X2213959Y-1326460D1* +X2220650Y-1323689D2* +X2216730Y-1323689D1* +X2240970Y-1323689D2* +X2220650Y-1323689D1* +X2243741Y-1326460D2* +X2240970Y-1323689D1* +X2267045Y-1353240D2* +X2243741Y-1326460D1* +X2302606Y-1389893D2* +X2267045Y-1353240D1* +X2309617Y-1396904D2* +X2302606Y-1389893D1* +X2329637Y-1396904D2* +X2309617Y-1396904D1* +X2331181Y-1398448D2* +X2329637Y-1396904D1* +X2349500Y-1427807D2* +X2331181Y-1398448D1* +X2349500Y-1442393D2* +X2349500Y-1427807D1* +X2352544Y-1446612D2* +X2349500Y-1442393D1* +X2360213Y-1454281D2* +X2352544Y-1446612D1* +X2360588Y-1454436D2* +X2360213Y-1454281D1* +X2373288Y-1454436D2* +X2360588Y-1454436D1* +X2384132Y-1454436D2* +X2373288Y-1454436D1* +X2384507Y-1454281D2* +X2384132Y-1454436D1* +X2392176Y-1446612D2* +X2384507Y-1454281D1* +X2392331Y-1446237D2* +X2392176Y-1446612D1* +X2393950Y-1441867D2* +X2392331Y-1446237D1* +X2393950Y-1439291D2* +X2393950Y-1441867D1* +X2393950Y-1435100D2* +X2393950Y-1439291D1* +X2144014Y-1333151D2* +X2152650Y-1336040D1* +X2140530Y-1333151D2* +X2144014Y-1333151D1* +X2113970Y-1323689D2* +X2140530Y-1333151D1* +X2093650Y-1323689D2* +X2113970Y-1323689D1* +X2089730Y-1323689D2* +X2093650Y-1323689D1* +X2050995Y-1330039D2* +X2089730Y-1323689D1* +X2048224Y-1332810D2* +X2050995Y-1330039D1* +X1997996Y-1392610D2* +X2048224Y-1332810D1* +X1995225Y-1395381D2* +X1997996Y-1392610D1* +X1973873Y-1396079D2* +X1995225Y-1395381D1* +X1973498Y-1396234D2* +X1973873Y-1396079D1* +X1931474Y-1416700D2* +X1973498Y-1396234D1* +X1924050Y-1424146D2* +X1931474Y-1416700D1* +X1924050Y-1429385D2* +X1924050Y-1424146D1* +X1924050Y-1430909D2* +X1924050Y-1429385D1* +X1924050Y-1435100D2* +X1924050Y-1430909D1* +X2432050Y-1439291D2* +X2432050Y-1435100D1* +X2432050Y-1441867D2* +X2432050Y-1439291D1* +X2419949Y-1456684D2* +X2432050Y-1441867D1* +X2407279Y-1469354D2* +X2419949Y-1456684D1* +X2399792Y-1476714D2* +X2407279Y-1469354D1* +X2399384Y-1476986D2* +X2399792Y-1476714D1* +X2389669Y-1481010D2* +X2399384Y-1476986D1* +X2389187Y-1481106D2* +X2389669Y-1481010D1* +X2368233Y-1481106D2* +X2389187Y-1481106D1* +X2355533Y-1481106D2* +X2368233Y-1481106D1* +X1908468Y-1454436D2* +X2355533Y-1481106D1* +X1908093Y-1454281D2* +X1908468Y-1454436D1* +X1904602Y-1450975D2* +X1908093Y-1454281D1* +X1898650Y-1445023D2* +X1904602Y-1450975D1* +X1898650Y-1440815D2* +X1898650Y-1445023D1* +X1898650Y-1439291D2* +X1898650Y-1440815D1* +X1898650Y-1435100D2* +X1898650Y-1439291D1* +X2432050Y-1342898D2* +X2432050Y-1339850D1* +X2416093Y-1352419D2* +X2432050Y-1342898D1* +X2408424Y-1360088D2* +X2416093Y-1352419D1* +X2408269Y-1360463D2* +X2408424Y-1360088D1* +X2406650Y-1364833D2* +X2408269Y-1360463D1* +X2406650Y-1367409D2* +X2406650Y-1364833D1* +X2406650Y-1371600D2* +X2406650Y-1367409D1* +X2381250Y-1342898D2* +X2381250Y-1339850D1* +X2381250Y-1367409D2* +X2381250Y-1342898D1* +X2381250Y-1371600D2* +X2381250Y-1367409D1* +X2330450Y-1342898D2* +X2330450Y-1339850D1* +X2354362Y-1363345D2* +X2330450Y-1342898D1* +X2355850Y-1364833D2* +X2354362Y-1363345D1* +X2355850Y-1365885D2* +X2355850Y-1364833D1* +X2355850Y-1367409D2* +X2355850Y-1365885D1* +X2355850Y-1371600D2* +X2355850Y-1367409D1* +X2282793Y-1349756D2* +X2279650Y-1339850D1* +X2282793Y-1353240D2* +X2282793Y-1349756D1* +X2311940Y-1390471D2* +X2282793Y-1353240D1* +X2313484Y-1392015D2* +X2311940Y-1390471D1* +X2333503Y-1392015D2* +X2313484Y-1392015D1* +X2340515Y-1399027D2* +X2333503Y-1392015D1* +X2355850Y-1424146D2* +X2340515Y-1399027D1* +X2355850Y-1429385D2* +X2355850Y-1424146D1* +X2355850Y-1430909D2* +X2355850Y-1429385D1* +X2355850Y-1435100D2* +X2355850Y-1430909D1* +X2457450Y-1260602D2* +X2457450Y-1263650D1* +X2419782Y-1181100D2* +X2457450Y-1260602D1* +X2419782Y-1174750D2* +X2419782Y-1181100D1* +X2406650Y-1260602D2* +X2406650Y-1263650D1* +X2349779Y-1181100D2* +X2406650Y-1260602D1* +X2349779Y-1174750D2* +X2349779Y-1181100D1* +X2355850Y-1260602D2* +X2355850Y-1263650D1* +X2279802Y-1181100D2* +X2355850Y-1260602D1* +X2279802Y-1174750D2* +X2279802Y-1181100D1* +X2305050Y-1260602D2* +X2305050Y-1263650D1* +X2209800Y-1181100D2* +X2305050Y-1260602D1* +X2209800Y-1174750D2* +X2209800Y-1181100D1* +X2279650Y-1260602D2* +X2279650Y-1263650D1* +X2174799Y-1181100D2* +X2279650Y-1260602D1* +X2174799Y-1174750D2* +X2174799Y-1181100D1* +X2330450Y-1260602D2* +X2330450Y-1263650D1* +X2244801Y-1181100D2* +X2330450Y-1260602D1* +X2244801Y-1174750D2* +X2244801Y-1181100D1* +X2381250Y-1260602D2* +X2381250Y-1263650D1* +X2314804Y-1181100D2* +X2381250Y-1260602D1* +X2314804Y-1174750D2* +X2314804Y-1181100D1* +X2432050Y-1260602D2* +X2432050Y-1263650D1* +X2384781Y-1181100D2* +X2432050Y-1260602D1* +X2384781Y-1174750D2* +X2384781Y-1181100D1* +X2482850Y-1260602D2* +X2482850Y-1263650D1* +X2454783Y-1181100D2* +X2482850Y-1260602D1* +X2454783Y-1174750D2* +X2454783Y-1181100D1* +X2342134Y-1370616D2* +X2343150Y-1371600D1* +X2338650Y-1370616D2* +X2342134Y-1370616D1* +X2334342Y-1367024D2* +X2338650Y-1370616D1* +X2305050Y-1342898D2* +X2334342Y-1367024D1* +X2305050Y-1339850D2* +X2305050Y-1342898D1* +X2355850Y-1342898D2* +X2355850Y-1339850D1* +X2366776Y-1360088D2* +X2355850Y-1342898D1* +X2366931Y-1360463D2* +X2366776Y-1360088D1* +X2368550Y-1364833D2* +X2366931Y-1360463D1* +X2368550Y-1367409D2* +X2368550Y-1364833D1* +X2368550Y-1371600D2* +X2368550Y-1367409D1* +X2406650Y-1342898D2* +X2406650Y-1339850D1* +X2395724Y-1360088D2* +X2406650Y-1342898D1* +X2395569Y-1360463D2* +X2395724Y-1360088D1* +X2393950Y-1364833D2* +X2395569Y-1360463D1* +X2393950Y-1367409D2* +X2393950Y-1364833D1* +X2393950Y-1371600D2* +X2393950Y-1367409D1* +X2457450Y-1342898D2* +X2457450Y-1339850D1* +X2437560Y-1355933D2* +X2457450Y-1342898D1* +X2420838Y-1363345D2* +X2437560Y-1355933D1* +X2419350Y-1364833D2* +X2420838Y-1363345D1* +X2419350Y-1365885D2* +X2419350Y-1364833D1* +X2419350Y-1367409D2* +X2419350Y-1365885D1* +X2419350Y-1371600D2* +X2419350Y-1367409D1* +X1962150Y-1342898D2* +X1962150Y-1339850D1* +X1946193Y-1352419D2* +X1962150Y-1342898D1* +X1938524Y-1360088D2* +X1946193Y-1352419D1* +X1938369Y-1360463D2* +X1938524Y-1360088D1* +X1936750Y-1364833D2* +X1938369Y-1360463D1* +X1936750Y-1367409D2* +X1936750Y-1364833D1* +X1936750Y-1371600D2* +X1936750Y-1367409D1* +X1911350Y-1342898D2* +X1911350Y-1339850D1* +X1911350Y-1367409D2* +X1911350Y-1342898D1* +X1911350Y-1371600D2* +X1911350Y-1367409D1* +X1860550Y-1342898D2* +X1860550Y-1339850D1* +X1884462Y-1363345D2* +X1860550Y-1342898D1* +X1885950Y-1364833D2* +X1884462Y-1363345D1* +X1885950Y-1365885D2* +X1885950Y-1364833D1* +X1885950Y-1367409D2* +X1885950Y-1365885D1* +X1885950Y-1371600D2* +X1885950Y-1367409D1* +X1816100Y-1346549D2* +X1809750Y-1339850D1* +X1819584Y-1346549D2* +X1816100Y-1346549D1* +X1822355Y-1349320D2* +X1819584Y-1346549D1* +X1885950Y-1428333D2* +X1822355Y-1349320D1* +X1885950Y-1430909D2* +X1885950Y-1428333D1* +X1885950Y-1435100D2* +X1885950Y-1430909D1* +X1987550Y-1260602D2* +X1987550Y-1263650D1* +X2045132Y-1181100D2* +X1987550Y-1260602D1* +X2045132Y-1174750D2* +X2045132Y-1181100D1* +X1936750Y-1260602D2* +X1936750Y-1263650D1* +X1975129Y-1181100D2* +X1936750Y-1260602D1* +X1975129Y-1174750D2* +X1975129Y-1181100D1* +X1885950Y-1260602D2* +X1885950Y-1263650D1* +X1905152Y-1181100D2* +X1885950Y-1260602D1* +X1905152Y-1174750D2* +X1905152Y-1181100D1* +X1835150Y-1260602D2* +X1835150Y-1263650D1* +X1835150Y-1181100D2* +X1835150Y-1260602D1* +X1835150Y-1174750D2* +X1835150Y-1181100D1* +X1809750Y-1260602D2* +X1809750Y-1263650D1* +X1800149Y-1181100D2* +X1809750Y-1260602D1* +X1800149Y-1174750D2* +X1800149Y-1181100D1* +X1860550Y-1260602D2* +X1860550Y-1263650D1* +X1870151Y-1181100D2* +X1860550Y-1260602D1* +X1870151Y-1174750D2* +X1870151Y-1181100D1* +X1911350Y-1260602D2* +X1911350Y-1263650D1* +X1940154Y-1181100D2* +X1911350Y-1260602D1* +X1940154Y-1174750D2* +X1940154Y-1181100D1* +X1962150Y-1260602D2* +X1962150Y-1263650D1* +X2010131Y-1181100D2* +X1962150Y-1260602D1* +X2010131Y-1174750D2* +X2010131Y-1181100D1* +X2012950Y-1260602D2* +X2012950Y-1263650D1* +X2080133Y-1181100D2* +X2012950Y-1260602D1* +X2080133Y-1174750D2* +X2080133Y-1181100D1* +X1872234Y-1370616D2* +X1873250Y-1371600D1* +X1868750Y-1370616D2* +X1872234Y-1370616D1* +X1835150Y-1342898D2* +X1868750Y-1370616D1* +X1835150Y-1339850D2* +X1835150Y-1342898D1* +X1885950Y-1342898D2* +X1885950Y-1339850D1* +X1896876Y-1360088D2* +X1885950Y-1342898D1* +X1897031Y-1360463D2* +X1896876Y-1360088D1* +X1898650Y-1364833D2* +X1897031Y-1360463D1* +X1898650Y-1367409D2* +X1898650Y-1364833D1* +X1898650Y-1371600D2* +X1898650Y-1367409D1* +X1936750Y-1342898D2* +X1936750Y-1339850D1* +X1925824Y-1360088D2* +X1936750Y-1342898D1* +X1925669Y-1360463D2* +X1925824Y-1360088D1* +X1924050Y-1364833D2* +X1925669Y-1360463D1* +X1924050Y-1367409D2* +X1924050Y-1364833D1* +X1924050Y-1371600D2* +X1924050Y-1367409D1* +X1987550Y-1342898D2* +X1987550Y-1339850D1* +X1967660Y-1355933D2* +X1987550Y-1342898D1* +X1950938Y-1363345D2* +X1967660Y-1355933D1* +X1949450Y-1364833D2* +X1950938Y-1363345D1* +X1949450Y-1365885D2* +X1949450Y-1364833D1* +X1949450Y-1367409D2* +X1949450Y-1365885D1* +X1949450Y-1371600D2* +X1949450Y-1367409D1* +X1985264Y-1434116D2* +X1991360Y-1430020D1* +X1963166Y-1434116D2* +X1985264Y-1434116D1* +X1962150Y-1435100D2* +X1963166Y-1434116D1* +X2196179Y-1329944D2* +X2190750Y-1336040D1* +X2196179Y-1326460D2* +X2196179Y-1329944D1* +X2198950Y-1323689D2* +X2196179Y-1326460D1* +X2212893Y-1314954D2* +X2198950Y-1323689D1* +X2213268Y-1314799D2* +X2212893Y-1314954D1* +X2224112Y-1314799D2* +X2213268Y-1314799D1* +X2244432Y-1314799D2* +X2224112Y-1314799D1* +X2289484Y-1323689D2* +X2244432Y-1314799D1* +X2292255Y-1326460D2* +X2289484Y-1323689D1* +X2292255Y-1330380D2* +X2292255Y-1326460D1* +X2292096Y-1331513D2* +X2292255Y-1330380D1* +X2292096Y-1337609D2* +X2292096Y-1331513D1* +X2292150Y-1348318D2* +X2292096Y-1337609D1* +X2299630Y-1355798D2* +X2292150Y-1348318D1* +X2338558Y-1379765D2* +X2299630Y-1355798D1* +X2339292Y-1380497D2* +X2338558Y-1379765D1* +X2342449Y-1382831D2* +X2339292Y-1380497D1* +X2354144Y-1394526D2* +X2342449Y-1382831D1* +X2366215Y-1415477D2* +X2354144Y-1394526D1* +X2368550Y-1421115D2* +X2366215Y-1415477D1* +X2368550Y-1429385D2* +X2368550Y-1421115D1* +X2368550Y-1430909D2* +X2368550Y-1429385D1* +X2368550Y-1435100D2* +X2368550Y-1430909D1* +X2263394Y-1453801D2* +X2272030Y-1451610D1* +X2154403Y-1453801D2* +X2263394Y-1453801D1* +X1944950Y-1445546D2* +X2154403Y-1453801D1* +X1938238Y-1443355D2* +X1944950Y-1445546D1* +X1936750Y-1441867D2* +X1938238Y-1443355D1* +X1936750Y-1440815D2* +X1936750Y-1441867D1* +X1936750Y-1439291D2* +X1936750Y-1440815D1* +X1936750Y-1435100D2* +X1936750Y-1439291D1* +X2280666Y-1454499D2* +X2272030Y-1451610D1* +X2284150Y-1454499D2* +X2280666Y-1454499D1* +X2357051Y-1472216D2* +X2284150Y-1454499D1* +X2374969Y-1472216D2* +X2357051Y-1472216D1* +X2377924Y-1471764D2* +X2374969Y-1472216D1* +X2386980Y-1468755D2* +X2377924Y-1471764D1* +X2392618Y-1466420D2* +X2386980Y-1468755D1* +X2404315Y-1454723D2* +X2392618Y-1466420D1* +X2406650Y-1449085D2* +X2404315Y-1454723D1* +X2406650Y-1440815D2* +X2406650Y-1449085D1* +X2406650Y-1439291D2* +X2406650Y-1440815D1* +X2406650Y-1435100D2* +X2406650Y-1439291D1* +X2196179Y-1375156D2* +X2190750Y-1369060D1* +X2196179Y-1378640D2* +X2196179Y-1375156D1* +X2197100Y-1416050D2* +X2196179Y-1378640D1* +X2197100Y-1422400D2* +X2197100Y-1416050D1* +X2263394Y-1421479D2* +X2272030Y-1418590D1* +X2259910Y-1421479D2* +X2263394Y-1421479D1* +X2257139Y-1424250D2* +X2259910Y-1421479D1* +X2247720Y-1435986D2* +X2257139Y-1424250D1* +X2239337Y-1444369D2* +X2247720Y-1435986D1* +X2238028Y-1444911D2* +X2239337Y-1444369D1* +X2226174Y-1444911D2* +X2238028Y-1444911D1* +X2156172Y-1444911D2* +X2226174Y-1444911D1* +X2154863Y-1444369D2* +X2156172Y-1444911D1* +X2127098Y-1428750D2* +X2154863Y-1444369D1* +X2127098Y-1422400D2* +X2127098Y-1428750D1* +X2012950Y-1336802D2* +X2012950Y-1339850D1* +X2115134Y-1181100D2* +X2012950Y-1336802D1* +X2115134Y-1174750D2* +X2115134Y-1181100D1* +X2012950Y-1342898D2* +X2012950Y-1339850D1* +X1982470Y-1376426D2* +X2012950Y-1342898D1* +X2482850Y-1336802D2* +X2482850Y-1339850D1* +X2495963Y-1272019D2* +X2482850Y-1336802D1* +X2495963Y-1261377D2* +X2495963Y-1272019D1* +X2495963Y-1255281D2* +X2495963Y-1261377D1* +X2489784Y-1181100D2* +X2495963Y-1255281D1* +X2489784Y-1174750D2* +X2489784Y-1181100D1* +X1962150Y-1375791D2* +X1962150Y-1371600D1* +X1962150Y-1378367D2* +X1962150Y-1375791D1* +X1960662Y-1379855D2* +X1962150Y-1378367D1* +X1923377Y-1408383D2* +X1960662Y-1379855D1* +X1913208Y-1418552D2* +X1923377Y-1408383D1* +X1911699Y-1422195D2* +X1913208Y-1418552D1* +X1911350Y-1428333D2* +X1911699Y-1422195D1* +X1911350Y-1430909D2* +X1911350Y-1428333D1* +X1911350Y-1435100D2* +X1911350Y-1430909D1* +X1963166Y-1372584D2* +X1962150Y-1371600D1* +X1966650Y-1372584D2* +X1963166Y-1372584D1* +X1982470Y-1376426D2* +X1966650Y-1372584D1* +X2432050Y-1375791D2* +X2432050Y-1371600D1* +X2432050Y-1378367D2* +X2432050Y-1375791D1* +X2430562Y-1379855D2* +X2432050Y-1378367D1* +X2382738Y-1426845D2* +X2430562Y-1379855D1* +X2381250Y-1428333D2* +X2382738Y-1426845D1* +X2381250Y-1429385D2* +X2381250Y-1428333D1* +X2381250Y-1430909D2* +X2381250Y-1429385D1* +X2381250Y-1435100D2* +X2381250Y-1430909D1* +X2433066Y-1370616D2* +X2432050Y-1371600D1* +X2436550Y-1370616D2* +X2433066Y-1370616D1* +X2462960Y-1355933D2* +X2436550Y-1370616D1* +X2482850Y-1342898D2* +X2462960Y-1355933D1* +X2482850Y-1339850D2* +X2482850Y-1342898D1* +X2489784Y-1168400D2* +X2489784Y-1174750D1* +X2462019Y-1152781D2* +X2489784Y-1168400D1* +X2460710Y-1152239D2* +X2462019Y-1152781D1* +X2180726Y-1152239D2* +X2460710Y-1152239D1* +X2168872Y-1152239D2* +X2180726Y-1152239D1* +X2115134Y-1168400D2* +X2168872Y-1152239D1* +X2115134Y-1174750D2* +X2115134Y-1168400D1* +X2096421Y-1375156D2* +X2101850Y-1369060D1* +X2096421Y-1378640D2* +X2096421Y-1375156D1* +X2092096Y-1416050D2* +X2096421Y-1378640D1* +X2092096Y-1422400D2* +X2092096Y-1416050D1* +X2327021Y-1384935D2* +X2321560Y-1384935D1* +X2334163Y-1384935D2* +X2327021Y-1384935D1* +X2334900Y-1385240D2* +X2334163Y-1384935D1* +X2339073Y-1387885D2* +X2334900Y-1385240D1* +X2349090Y-1397902D2* +X2339073Y-1387885D1* +X2361218Y-1420512D2* +X2349090Y-1397902D1* +X2362200Y-1422883D2* +X2361218Y-1420512D1* +X2362200Y-1442393D2* +X2362200Y-1422883D1* +X2364432Y-1444625D2* +X2362200Y-1442393D1* +X2366590Y-1445546D2* +X2364432Y-1444625D1* +X2369130Y-1445546D2* +X2366590Y-1445546D1* +X2373050Y-1445546D2* +X2369130Y-1445546D1* +X2379762Y-1443355D2* +X2373050Y-1445546D1* +X2381250Y-1441867D2* +X2379762Y-1443355D1* +X2381250Y-1440815D2* +X2381250Y-1441867D1* +X2381250Y-1439291D2* +X2381250Y-1440815D1* +X2381250Y-1435100D2* +X2381250Y-1439291D1* +X1984026Y-1383284D2* +X1986280Y-1386205D1* +X1984026Y-1379800D2* +X1984026Y-1383284D1* +X1982470Y-1376426D2* +X1984026Y-1379800D1* +G54D19* +X2279650Y-1260602D2* +X2279650Y-1266698D1* +X2305050Y-1260602D2* +X2305050Y-1266698D1* +X2330450Y-1260602D2* +X2330450Y-1266698D1* +X2355850Y-1260602D2* +X2355850Y-1266698D1* +X2381250Y-1260602D2* +X2381250Y-1266698D1* +X2406650Y-1260602D2* +X2406650Y-1266698D1* +X2432050Y-1260602D2* +X2432050Y-1266698D1* +X2457450Y-1260602D2* +X2457450Y-1266698D1* +X2482850Y-1260602D2* +X2482850Y-1266698D1* +X2482850Y-1336802D2* +X2482850Y-1342898D1* +X2457450Y-1336802D2* +X2457450Y-1342898D1* +X2432050Y-1336802D2* +X2432050Y-1342898D1* +X2406650Y-1336802D2* +X2406650Y-1342898D1* +X2381250Y-1336802D2* +X2381250Y-1342898D1* +X2355850Y-1336802D2* +X2355850Y-1342898D1* +X2330450Y-1336802D2* +X2330450Y-1342898D1* +X2305050Y-1336802D2* +X2305050Y-1342898D1* +X1809750Y-1260602D2* +X1809750Y-1266698D1* +X1835150Y-1260602D2* +X1835150Y-1266698D1* +X1860550Y-1260602D2* +X1860550Y-1266698D1* +X1885950Y-1260602D2* +X1885950Y-1266698D1* +X1911350Y-1260602D2* +X1911350Y-1266698D1* +X1936750Y-1260602D2* +X1936750Y-1266698D1* +X1962150Y-1260602D2* +X1962150Y-1266698D1* +X1987550Y-1260602D2* +X1987550Y-1266698D1* +X2012950Y-1260602D2* +X2012950Y-1266698D1* +X2012950Y-1336802D2* +X2012950Y-1342898D1* +X1987550Y-1336802D2* +X1987550Y-1342898D1* +X1962150Y-1336802D2* +X1962150Y-1342898D1* +X1936750Y-1336802D2* +X1936750Y-1342898D1* +X1911350Y-1336802D2* +X1911350Y-1342898D1* +X1885950Y-1336802D2* +X1885950Y-1342898D1* +X1860550Y-1336802D2* +X1860550Y-1342898D1* +X1835150Y-1336802D2* +X1835150Y-1342898D1* +G54D22* +X2162099Y-1428750D2* +X2162099Y-1416050D1* +X2197100Y-1428750D2* +X2197100Y-1416050D1* +X2232101Y-1428750D2* +X2232101Y-1416050D1* +X2127098Y-1428750D2* +X2127098Y-1416050D1* +X2057095Y-1428750D2* +X2057095Y-1416050D1* +X2092096Y-1428750D2* +X2092096Y-1416050D1* +X2244801Y-1168400D2* +X2244801Y-1181100D1* +X2209800Y-1168400D2* +X2209800Y-1181100D1* +X2174799Y-1168400D2* +X2174799Y-1181100D1* +X2279802Y-1168400D2* +X2279802Y-1181100D1* +X2314804Y-1168400D2* +X2314804Y-1181100D1* +X2489784Y-1168400D2* +X2489784Y-1181100D1* +X2454783Y-1168400D2* +X2454783Y-1181100D1* +X2349779Y-1168400D2* +X2349779Y-1181100D1* +X2384781Y-1168400D2* +X2384781Y-1181100D1* +X2419782Y-1168400D2* +X2419782Y-1181100D1* +X1870151Y-1168400D2* +X1870151Y-1181100D1* +X1835150Y-1168400D2* +X1835150Y-1181100D1* +X1800149Y-1168400D2* +X1800149Y-1181100D1* +X1905152Y-1168400D2* +X1905152Y-1181100D1* +X1940154Y-1168400D2* +X1940154Y-1181100D1* +X2115134Y-1168400D2* +X2115134Y-1181100D1* +X2080133Y-1168400D2* +X2080133Y-1181100D1* +X1975129Y-1168400D2* +X1975129Y-1181100D1* +X2010131Y-1168400D2* +X2010131Y-1181100D1* +X2045132Y-1168400D2* +X2045132Y-1181100D1* +M02* diff --git a/gerbview/gerber_test_files/apertures_rotated_and_arcs_in_tracks.gbr b/gerbview/gerber_test_files/apertures_rotated_and_arcs_in_tracks.gbr new file mode 100644 index 0000000..a335a27 --- /dev/null +++ b/gerbview/gerber_test_files/apertures_rotated_and_arcs_in_tracks.gbr @@ -0,0 +1,1417 @@ +%ICAS*% +%FSLAX44Y44*% +%OFA0B0*% +%SFA1B1*% +%MOMM*% +%AMFRECTNOHOLE10* +21,1,1.5748,2.2860,0.0000,0.0000,0* +% +%AMFRECTNOHOLE11* +21,1,0.5080,1.1430,0.0000,0.0000,180* +% +%AMFRECTNOHOLE12* +21,1,1.5240,2.0320,0.0000,0.0000,180* +% +%AMFRECTNOHOLE13* +21,1,1.5240,2.0320,0.0000,0.0000,270* +% +%AMFRECTNOHOLE14* +21,1,1.5240,2.0320,0.0000,0.0000,90* +% +%AMFRECTNOHOLE15* +21,1,0.8890,1.3970,0.0000,0.0000,270* +% +%ADD10FRECTNOHOLE10*% +%ADD11FRECTNOHOLE11*% +%ADD12FRECTNOHOLE12*% +%ADD13FRECTNOHOLE13*% +%ADD14FRECTNOHOLE14*% +%ADD15FRECTNOHOLE15*% +%ADD17C,0.3048X0.0000X0.0000*% +%ADD19C,1.6764X0.0000X0.0000*% +%ADD22C,2.2860X0.0000X0.0000*% +%LNBottom_arc*% +G54D10* +X2279650Y-1339850D3* +X1809750Y-1339850D3* +G54D11* +X2355850Y-1435100D3* +X2343150Y-1371600D3* +X2355850Y-1371600D3* +X2368550Y-1371600D3* +X2381250Y-1371600D3* +X2393950Y-1371600D3* +X2406650Y-1371600D3* +X2419350Y-1371600D3* +X2432050Y-1371600D3* +X2432050Y-1435100D3* +X2419350Y-1435100D3* +X2406650Y-1435100D3* +X2393950Y-1435100D3* +X2381250Y-1435100D3* +X2368550Y-1435100D3* +X2343150Y-1435100D3* +X1885950Y-1435100D3* +X1873250Y-1371600D3* +X1885950Y-1371600D3* +X1898650Y-1371600D3* +X1911350Y-1371600D3* +X1924050Y-1371600D3* +X1936750Y-1371600D3* +X1949450Y-1371600D3* +X1962150Y-1371600D3* +X1962150Y-1435100D3* +X1949450Y-1435100D3* +X1936750Y-1435100D3* +X1924050Y-1435100D3* +X1911350Y-1435100D3* +X1898650Y-1435100D3* +X1873250Y-1435100D3* +G54D12* +X2024380Y-1430020D3* +X1991360Y-1430020D3* +G54D13* +X2272030Y-1418590D3* +X2272030Y-1451610D3* +G54D14* +X2101850Y-1369060D3* +X2101850Y-1336040D3* +X2228850Y-1369060D3* +X2228850Y-1336040D3* +X2190750Y-1369060D3* +X2190750Y-1336040D3* +X2152650Y-1369060D3* +X2152650Y-1336040D3* +G54D15* +X1986280Y-1386205D3* +X1986280Y-1405255D3* +X2321560Y-1384935D3* +X2321560Y-1403985D3* +X2059940Y-1339215D3* +X2059940Y-1358265D3* +G54D17* +X1947035Y-1424656D2* +X1948180Y-1424686D1* +G75* +G01X1947035Y-1424656D2* +G03X1946910Y-1424654I-125J-4729D1* +G74* +X1939290Y-1424654D2* +X1946910Y-1424654D1* +G75* +G01X1939290Y-1424654D2* +G03X1938432Y-1424732I0J-4731D1* +G74* +X1933519Y-1425638D2* +X1938432Y-1424732D1* +G75* +G01X1933519Y-1425638D2* +G03X1930400Y-1429385I691J-3747D1* +G74* +X1930400Y-1440815D2* +X1930400Y-1429385D1* +G75* +G01X1927972Y-1444366D2* +G03X1930400Y-1440815I-1382J3551D1* +G74* +X1925765Y-1445224D2* +X1927972Y-1444366D1* +G75* +G01X1924050Y-1445546D2* +G03X1925765Y-1445224I0J4731D1* +G74* +X1911350Y-1445546D2* +X1924050Y-1445546D1* +G75* +G01X1909635Y-1445224D2* +G03X1911350Y-1445546I1715J4409D1* +G74* +X1907428Y-1444366D2* +X1909635Y-1445224D1* +G75* +G01X1905000Y-1440815D2* +G03X1907428Y-1444366I3810J0D1* +G74* +X1905000Y-1429385D2* +X1905000Y-1440815D1* +G75* +G01X1905000Y-1429385D2* +G03X1902572Y-1425834I-3810J0D1* +G74* +X1900365Y-1424976D2* +X1902572Y-1425834D1* +G75* +G01X1900365Y-1424976D2* +G03X1896935Y-1424976I-1715J-4409D1* +G74* +X1894728Y-1425834D2* +X1896935Y-1424976D1* +G75* +G01X1894728Y-1425834D2* +G03X1892300Y-1429385I1382J-3551D1* +G74* +X1892300Y-1440815D2* +X1892300Y-1429385D1* +G75* +G01X1889872Y-1444366D2* +G03X1892300Y-1440815I-1382J3551D1* +G74* +X1887665Y-1445224D2* +X1889872Y-1444366D1* +G75* +G01X1885950Y-1445546D2* +G03X1887665Y-1445224I0J4731D1* +G74* +X1883410Y-1445546D2* +X1885950Y-1445546D1* +G75* +G01X1882050Y-1445346D2* +G03X1883410Y-1445546I1360J4531D1* +G74* +X1875060Y-1443248D2* +X1882050Y-1445346D1* +G75* +G01X1873250Y-1440815D2* +G03X1875060Y-1443248I2540J0D1* +G74* +X1873250Y-1439291D2* +X1873250Y-1440815D1* +X1873250Y-1435100D2* +X1873250Y-1439291D1* +X1949348Y-1428671D2* +X1948180Y-1424686D1* +G75* +G01X1949450Y-1429385D2* +G03X1949348Y-1428671I-2540J0D1* +G74* +X1949450Y-1430909D2* +X1949450Y-1429385D1* +X1949450Y-1435100D2* +X1949450Y-1430909D1* +X2343150Y-1439291D2* +X2343150Y-1440815D1* +X2343150Y-1435100D2* +X2343150Y-1439291D1* +G75* +G01X2343150Y-1440815D2* +G03X2343586Y-1444115I12700J0D1* +G74* +X2344272Y-1446664D2* +X2343586Y-1444115D1* +G75* +G01X2344272Y-1446664D2* +G03X2366010Y-1463326I21738J5849D1* +G74* +X2371090Y-1463326D2* +X2366010Y-1463326D1* +G75* +G01X2371090Y-1463326D2* +G03X2373811Y-1463161I0J22511D1* +G74* +X2381320Y-1462247D2* +X2373811Y-1463161D1* +G75* +G01X2381320Y-1462247D2* +G03X2400300Y-1440815I-2610J21432D1* +G74* +X2400300Y-1429385D2* +X2400300Y-1440815D1* +G75* +G01X2402728Y-1425834D2* +G03X2400300Y-1429385I1382J-3551D1* +G74* +X2404935Y-1424976D2* +X2402728Y-1425834D1* +G75* +G01X2406650Y-1424654D2* +G03X2404935Y-1424976I0J-4731D1* +G74* +X2409190Y-1424654D2* +X2406650Y-1424654D1* +G75* +G01X2410550Y-1424854D2* +G03X2409190Y-1424654I-1360J-4531D1* +G74* +X2417540Y-1426952D2* +X2410550Y-1424854D1* +G75* +G01X2419350Y-1429385D2* +G03X2417540Y-1426952I-2540J0D1* +G74* +X2419350Y-1430909D2* +X2419350Y-1429385D1* +X2419350Y-1435100D2* +X2419350Y-1430909D1* +X2223421Y-1343660D2* +X2223262Y-1348486D1* +X2223421Y-1342136D2* +X2223421Y-1343660D1* +X2228850Y-1336040D2* +X2223421Y-1342136D1* +X2206079Y-1355801D2* +X2223262Y-1348486D1* +G75* +G01X2200910Y-1356856D2* +G03X2206079Y-1355801I0J13196D1* +G74* +X2180590Y-1356856D2* +X2200910Y-1356856D1* +G75* +G01X2177658Y-1356526D2* +G03X2180590Y-1356856I2932J12866D1* +G74* +X2141439Y-1348273D2* +X2177658Y-1356526D1* +G75* +G01X2141021Y-1348157D2* +G03X2141439Y-1348273I1469J4497D1* +G74* +X2113479Y-1339163D2* +X2141021Y-1348157D1* +G75* +G01X2113479Y-1339163D2* +G03X2112010Y-1338929I-1469J-4497D1* +G74* +X2110486Y-1338929D2* +X2112010Y-1338929D1* +X2101850Y-1336040D2* +X2110486Y-1338929D1* +X2090454Y-1339093D2* +X2072640Y-1343914D1* +G75* +G01X2091690Y-1338929D2* +G03X2090454Y-1339093I0J-4731D1* +G74* +X2093214Y-1338929D2* +X2091690Y-1338929D1* +X2101850Y-1336040D2* +X2093214Y-1338929D1* +X1991741Y-1405255D2* +X1993265Y-1405255D1* +X1986280Y-1405255D2* +X1991741Y-1405255D1* +G75* +G01X1993265Y-1405255D2* +G03X1995173Y-1404825I0J4445D1* +G74* +X1999113Y-1402952D2* +X1995173Y-1404825D1* +G75* +G01X1999113Y-1402952D2* +G03X2000651Y-1402095I-5848J12302D1* +G74* +X2055520Y-1366685D2* +X2000651Y-1402095D1* +G75* +G01X2055520Y-1366685D2* +G03X2057686Y-1362710I-2565J3975D1* +G74* +X2057686Y-1361186D2* +X2057686Y-1362710D1* +X2059940Y-1358265D2* +X2057686Y-1361186D1* +X2070716Y-1346491D2* +X2072640Y-1343914D1* +G75* +G01X2068648Y-1348066D2* +G03X2070716Y-1346491I-1723J4406D1* +G74* +X2065202Y-1349414D2* +X2068648Y-1348066D1* +G75* +G01X2065202Y-1349414D2* +G03X2062194Y-1353820I1723J-4406D1* +G74* +X2062194Y-1355344D2* +X2062194Y-1353820D1* +X2059940Y-1358265D2* +X2062194Y-1355344D1* +X2070500Y-1341018D2* +X2072640Y-1343914D1* +G75* +G01X2070500Y-1341018D2* +G03X2066925Y-1339215I-3575J-2642D1* +G74* +X2065401Y-1339215D2* +X2066925Y-1339215D1* +X2059940Y-1339215D2* +X2065401Y-1339215D1* +X2241086Y-1357189D2* +X2223262Y-1348486D1* +G75* +G01X2241707Y-1357553D2* +G03X2241086Y-1357189I-2697J-3887D1* +G74* +X2303714Y-1400585D2* +X2241707Y-1357553D1* +G75* +G01X2303714Y-1400585D2* +G03X2314575Y-1403985I10861J15650D1* +G74* +X2316099Y-1403985D2* +X2314575Y-1403985D1* +X2321560Y-1403985D2* +X2316099Y-1403985D1* +X2342134Y-1434116D2* +X2340610Y-1434116D1* +X2343150Y-1435100D2* +X2342134Y-1434116D1* +G75* +G01X2336510Y-1431746D2* +G03X2340610Y-1434116I4100J2361D1* +G74* +X2324445Y-1410791D2* +X2336510Y-1431746D1* +G75* +G01X2323814Y-1408430D2* +G03X2324445Y-1410791I4731J0D1* +G74* +X2323814Y-1406906D2* +X2323814Y-1408430D1* +X2321560Y-1403985D2* +X2323814Y-1406906D1* +X1976867Y-1405977D2* +X1948180Y-1424686D1* +G75* +G01X1979295Y-1405255D2* +G03X1976867Y-1405977I0J-4445D1* +G74* +X1980819Y-1405255D2* +X1979295Y-1405255D1* +X1986280Y-1405255D2* +X1980819Y-1405255D1* +X2057095Y-1422400D2* +X2057095Y-1426210D1* +X2032000Y-1426210D2* +X2057095Y-1426210D1* +X2030476Y-1426210D2* +X2032000Y-1426210D1* +X2024380Y-1430020D2* +X2030476Y-1426210D1* +X2162099Y-1422400D2* +X2162099Y-1416050D1* +X2158104Y-1377164D2* +X2162099Y-1416050D1* +G75* +G01X2158079Y-1376680D2* +G03X2158104Y-1377164I4731J0D1* +G74* +X2158079Y-1375156D2* +X2158079Y-1376680D1* +X2152650Y-1369060D2* +X2158079Y-1375156D1* +X2232101Y-1422400D2* +X2232101Y-1416050D1* +X2232101Y-1376680D2* +X2232101Y-1416050D1* +X2232101Y-1375156D2* +X2232101Y-1376680D1* +X2228850Y-1369060D2* +X2232101Y-1375156D1* +X2393950Y-1439291D2* +X2393950Y-1440815D1* +X2393950Y-1435100D2* +X2393950Y-1439291D1* +G75* +G01X2393626Y-1442056D2* +G03X2393950Y-1440815I-2216J1241D1* +G74* +X2390595Y-1447470D2* +X2393626Y-1442056D1* +G75* +G01X2378710Y-1454436D2* +G03X2390595Y-1447470I0J13621D1* +G74* +X2366010Y-1454436D2* +X2378710Y-1454436D1* +G75* +G01X2355488Y-1449464D2* +G03X2366010Y-1454436I10522J8649D1* +G74* +X2350367Y-1443234D2* +X2355488Y-1449464D1* +G75* +G01X2349500Y-1440815D2* +G03X2350367Y-1443234I3810J0D1* +G74* +X2349500Y-1429385D2* +X2349500Y-1440815D1* +G75* +G01X2349500Y-1429385D2* +G03X2348927Y-1427376I-3810J0D1* +G74* +X2330785Y-1398150D2* +X2348927Y-1427376D1* +G75* +G01X2330785Y-1398150D2* +G03X2328545Y-1396904I-2240J-1390D1* +G74* +X2314575Y-1396904D2* +X2328545Y-1396904D1* +G75* +G01X2305992Y-1393277D2* +G03X2314575Y-1396904I8583J8342D1* +G74* +X2268383Y-1354577D2* +X2305992Y-1393277D1* +G75* +G01X2268227Y-1354409D2* +G03X2268383Y-1354577I3549J3129D1* +G74* +X2242559Y-1325291D2* +X2268227Y-1354409D1* +G75* +G01X2242559Y-1325291D2* +G03X2239010Y-1323689I-3549J-3129D1* +G74* +X2218690Y-1323689D2* +X2239010Y-1323689D1* +G75* +G01X2218690Y-1323689D2* +G03X2214436Y-1326349I0J-4731D1* +G74* +X2205031Y-1345667D2* +X2214436Y-1326349D1* +G75* +G01X2200910Y-1348244D2* +G03X2205031Y-1345667I0J4584D1* +G74* +X2180590Y-1348244D2* +X2200910Y-1348244D1* +G75* +G01X2178188Y-1347565D2* +G03X2180590Y-1348244I2402J3905D1* +G74* +X2165289Y-1339630D2* +X2178188Y-1347565D1* +G75* +G01X2165289Y-1339630D2* +G03X2162810Y-1338929I-2479J-4030D1* +G74* +X2161286Y-1338929D2* +X2162810Y-1338929D1* +X2152650Y-1336040D2* +X2161286Y-1338929D1* +X1924050Y-1430909D2* +X1924050Y-1429385D1* +X1924050Y-1435100D2* +X1924050Y-1430909D1* +G75* +G01X1931192Y-1417966D2* +G03X1924050Y-1429385I5558J-11419D1* +G74* +X1973334Y-1397453D2* +X1931192Y-1417966D1* +G75* +G01X1978636Y-1396095D2* +G03X1973334Y-1397453I659J-13605D1* +G74* +X1993494Y-1395375D2* +X1978636Y-1396095D1* +G75* +G01X1993494Y-1395375D2* +G03X1996876Y-1393706I-229J4725D1* +G74* +X2049344Y-1331714D2* +X1996876Y-1393706D1* +G75* +G01X2052190Y-1330101D2* +G03X2049344Y-1331714I765J-4669D1* +G74* +X2090925Y-1323751D2* +X2052190Y-1330101D1* +G75* +G01X2091690Y-1323689D2* +G03X2090925Y-1323751I0J-4731D1* +G74* +X2112010Y-1323689D2* +X2091690Y-1323689D1* +G75* +G01X2113479Y-1323923D2* +G03X2112010Y-1323689I-1469J-4497D1* +G74* +X2141021Y-1332917D2* +X2113479Y-1323923D1* +G75* +G01X2141021Y-1332917D2* +G03X2142490Y-1333151I1469J4497D1* +G74* +X2144014Y-1333151D2* +X2142490Y-1333151D1* +X2152650Y-1336040D2* +X2144014Y-1333151D1* +X1898650Y-1439291D2* +X1898650Y-1440815D1* +X1898650Y-1435100D2* +X1898650Y-1439291D1* +G75* +G01X1898650Y-1440815D2* +G03X1906745Y-1452651I12700J0D1* +G74* +X1908951Y-1453509D2* +X1906745Y-1452651D1* +G75* +G01X1908951Y-1453509D2* +G03X1913087Y-1454412I4939J12694D1* +G74* +X2363633Y-1481036D2* +X1913087Y-1454412D1* +G75* +G01X2363633Y-1481036D2* +G03X2366010Y-1481106I2377J40221D1* +G74* +X2378710Y-1481106D2* +X2366010Y-1481106D1* +G75* +G01X2378710Y-1481106D2* +G03X2406914Y-1469589I0J40291D1* +G74* +X2413391Y-1463240D2* +X2406914Y-1469589D1* +G75* +G01X2413391Y-1463240D2* +G03X2415196Y-1461314I-21981J22425D1* +G74* +X2431434Y-1442473D2* +X2415196Y-1461314D1* +G75* +G01X2431434Y-1442473D2* +G03X2432050Y-1440815I-1924J1658D1* +G74* +X2432050Y-1439291D2* +X2432050Y-1440815D1* +X2432050Y-1435100D2* +X2432050Y-1439291D1* +X2406650Y-1367409D2* +X2406650Y-1365885D1* +X2406650Y-1371600D2* +X2406650Y-1367409D1* +G75* +G01X2406974Y-1364644D2* +G03X2406650Y-1365885I2216J-1241D1* +G74* +X2410005Y-1359230D2* +X2406974Y-1364644D1* +G75* +G01X2414404Y-1354505D2* +G03X2410005Y-1359230I7486J-11380D1* +G74* +X2432050Y-1342898D2* +X2414404Y-1354505D1* +X2432050Y-1339850D2* +X2432050Y-1342898D1* +X2381250Y-1367409D2* +X2381250Y-1365885D1* +X2381250Y-1371600D2* +X2381250Y-1367409D1* +X2381250Y-1342898D2* +X2381250Y-1365885D1* +X2381250Y-1339850D2* +X2381250Y-1342898D1* +X2355850Y-1367409D2* +X2355850Y-1365885D1* +X2355850Y-1371600D2* +X2355850Y-1367409D1* +G75* +G01X2355850Y-1365885D2* +G03X2354965Y-1363958I-2540J0D1* +G74* +X2330450Y-1342898D2* +X2354965Y-1363958D1* +X2330450Y-1339850D2* +X2330450Y-1342898D1* +X2355850Y-1430909D2* +X2355850Y-1429385D1* +X2355850Y-1435100D2* +X2355850Y-1430909D1* +G75* +G01X2355850Y-1429385D2* +G03X2353999Y-1422782I-12700J0D1* +G74* +X2338770Y-1397762D2* +X2353999Y-1422782D1* +G75* +G01X2338770Y-1397762D2* +G03X2328545Y-1392015I-10225J-6223D1* +G74* +X2314575Y-1392015D2* +X2328545Y-1392015D1* +G75* +G01X2312497Y-1391000D2* +G03X2314575Y-1392015I2078J1620D1* +G74* +X2283793Y-1354189D2* +X2312497Y-1391000D1* +G75* +G01X2282793Y-1351280D2* +G03X2283793Y-1354189I4731J0D1* +G74* +X2282793Y-1349756D2* +X2282793Y-1351280D1* +X2279650Y-1339850D2* +X2282793Y-1349756D1* +X2419782Y-1174750D2* +X2419782Y-1181100D1* +X2457450Y-1260602D2* +X2419782Y-1181100D1* +X2457450Y-1263650D2* +X2457450Y-1260602D1* +X2349779Y-1174750D2* +X2349779Y-1181100D1* +X2406650Y-1260602D2* +X2349779Y-1181100D1* +X2406650Y-1263650D2* +X2406650Y-1260602D1* +X2279802Y-1174750D2* +X2279802Y-1181100D1* +X2355850Y-1260602D2* +X2279802Y-1181100D1* +X2355850Y-1263650D2* +X2355850Y-1260602D1* +X2209800Y-1174750D2* +X2209800Y-1181100D1* +X2305050Y-1260602D2* +X2209800Y-1181100D1* +X2305050Y-1263650D2* +X2305050Y-1260602D1* +X2174799Y-1174750D2* +X2174799Y-1181100D1* +X2279650Y-1260602D2* +X2174799Y-1181100D1* +X2279650Y-1263650D2* +X2279650Y-1260602D1* +X2244801Y-1174750D2* +X2244801Y-1181100D1* +X2330450Y-1260602D2* +X2244801Y-1181100D1* +X2330450Y-1263650D2* +X2330450Y-1260602D1* +X2314804Y-1174750D2* +X2314804Y-1181100D1* +X2381250Y-1260602D2* +X2314804Y-1181100D1* +X2381250Y-1263650D2* +X2381250Y-1260602D1* +X2384781Y-1174750D2* +X2384781Y-1181100D1* +X2432050Y-1260602D2* +X2384781Y-1181100D1* +X2432050Y-1263650D2* +X2432050Y-1260602D1* +X2454783Y-1174750D2* +X2454783Y-1181100D1* +X2482850Y-1260602D2* +X2454783Y-1181100D1* +X2482850Y-1263650D2* +X2482850Y-1260602D1* +X2305050Y-1339850D2* +X2305050Y-1342898D1* +X2337614Y-1369546D2* +X2305050Y-1342898D1* +G75* +G01X2337614Y-1369546D2* +G03X2340610Y-1370616I2996J3661D1* +G74* +X2342134Y-1370616D2* +X2340610Y-1370616D1* +X2343150Y-1371600D2* +X2342134Y-1370616D1* +X2368550Y-1367409D2* +X2368550Y-1365885D1* +X2368550Y-1371600D2* +X2368550Y-1367409D1* +G75* +G01X2368550Y-1365885D2* +G03X2368226Y-1364644I-2540J0D1* +G74* +X2365195Y-1359230D2* +X2368226Y-1364644D1* +X2365195Y-1359230D2* +X2365132Y-1359120D1* +X2355850Y-1342898D2* +X2365132Y-1359120D1* +X2355850Y-1339850D2* +X2355850Y-1342898D1* +X2393950Y-1367409D2* +X2393950Y-1365885D1* +X2393950Y-1371600D2* +X2393950Y-1367409D1* +G75* +G01X2394274Y-1364644D2* +G03X2393950Y-1365885I2216J-1241D1* +G74* +X2397305Y-1359230D2* +X2394274Y-1364644D1* +X2397368Y-1359120D2* +X2397305Y-1359230D1* +X2406650Y-1342898D2* +X2397368Y-1359120D1* +X2406650Y-1339850D2* +X2406650Y-1342898D1* +X2419350Y-1367409D2* +X2419350Y-1365885D1* +X2419350Y-1371600D2* +X2419350Y-1367409D1* +G75* +G01X2420712Y-1363635D2* +G03X2419350Y-1365885I1178J-2250D1* +G74* +X2438132Y-1354515D2* +X2420712Y-1363635D1* +G75* +G01X2438132Y-1354515D2* +G03X2438820Y-1354128I-6082J11617D1* +G74* +X2457450Y-1342898D2* +X2438820Y-1354128D1* +X2457450Y-1339850D2* +X2457450Y-1342898D1* +X1936750Y-1367409D2* +X1936750Y-1365885D1* +X1936750Y-1371600D2* +X1936750Y-1367409D1* +G75* +G01X1937074Y-1364644D2* +G03X1936750Y-1365885I2216J-1241D1* +G74* +X1940105Y-1359230D2* +X1937074Y-1364644D1* +G75* +G01X1944504Y-1354505D2* +G03X1940105Y-1359230I7486J-11380D1* +G74* +X1962150Y-1342898D2* +X1944504Y-1354505D1* +X1962150Y-1339850D2* +X1962150Y-1342898D1* +X1911350Y-1367409D2* +X1911350Y-1365885D1* +X1911350Y-1371600D2* +X1911350Y-1367409D1* +X1911350Y-1342898D2* +X1911350Y-1365885D1* +X1911350Y-1339850D2* +X1911350Y-1342898D1* +X1885950Y-1367409D2* +X1885950Y-1365885D1* +X1885950Y-1371600D2* +X1885950Y-1367409D1* +G75* +G01X1885950Y-1365885D2* +G03X1885065Y-1363958I-2540J0D1* +G74* +X1860550Y-1342898D2* +X1885065Y-1363958D1* +X1860550Y-1339850D2* +X1860550Y-1342898D1* +X1885950Y-1430909D2* +X1885950Y-1429385D1* +X1885950Y-1435100D2* +X1885950Y-1430909D1* +G75* +G01X1885950Y-1429385D2* +G03X1885387Y-1427791I-2540J0D1* +G74* +X1821307Y-1348311D2* +X1885387Y-1427791D1* +G75* +G01X1821307Y-1348311D2* +G03X1817624Y-1346549I-3683J-2969D1* +G74* +X1816100Y-1346549D2* +X1817624Y-1346549D1* +X1809750Y-1339850D2* +X1816100Y-1346549D1* +X2045132Y-1174750D2* +X2045132Y-1181100D1* +X1987550Y-1260602D2* +X2045132Y-1181100D1* +X1987550Y-1263650D2* +X1987550Y-1260602D1* +X1975129Y-1174750D2* +X1975129Y-1181100D1* +X1936750Y-1260602D2* +X1975129Y-1181100D1* +X1936750Y-1263650D2* +X1936750Y-1260602D1* +X1905152Y-1174750D2* +X1905152Y-1181100D1* +X1885950Y-1260602D2* +X1905152Y-1181100D1* +X1885950Y-1263650D2* +X1885950Y-1260602D1* +X1835150Y-1174750D2* +X1835150Y-1181100D1* +X1835150Y-1260602D2* +X1835150Y-1181100D1* +X1835150Y-1263650D2* +X1835150Y-1260602D1* +X1800149Y-1174750D2* +X1800149Y-1181100D1* +X1809750Y-1260602D2* +X1800149Y-1181100D1* +X1809750Y-1263650D2* +X1809750Y-1260602D1* +X1870151Y-1174750D2* +X1870151Y-1181100D1* +X1860550Y-1260602D2* +X1870151Y-1181100D1* +X1860550Y-1263650D2* +X1860550Y-1260602D1* +X1940154Y-1174750D2* +X1940154Y-1181100D1* +X1911350Y-1260602D2* +X1940154Y-1181100D1* +X1911350Y-1263650D2* +X1911350Y-1260602D1* +X2010131Y-1174750D2* +X2010131Y-1181100D1* +X1962150Y-1260602D2* +X2010131Y-1181100D1* +X1962150Y-1263650D2* +X1962150Y-1260602D1* +X2080133Y-1174750D2* +X2080133Y-1181100D1* +X2012950Y-1260602D2* +X2080133Y-1181100D1* +X2012950Y-1263650D2* +X2012950Y-1260602D1* +X1835150Y-1339850D2* +X1835150Y-1342898D1* +X1867714Y-1369546D2* +X1835150Y-1342898D1* +G75* +G01X1867714Y-1369546D2* +G03X1870710Y-1370616I2996J3661D1* +G74* +X1872234Y-1370616D2* +X1870710Y-1370616D1* +X1873250Y-1371600D2* +X1872234Y-1370616D1* +X1898650Y-1367409D2* +X1898650Y-1365885D1* +X1898650Y-1371600D2* +X1898650Y-1367409D1* +G75* +G01X1898650Y-1365885D2* +G03X1898326Y-1364644I-2540J0D1* +G74* +X1895295Y-1359230D2* +X1898326Y-1364644D1* +X1895295Y-1359230D2* +X1895232Y-1359120D1* +X1885950Y-1342898D2* +X1895232Y-1359120D1* +X1885950Y-1339850D2* +X1885950Y-1342898D1* +X1924050Y-1367409D2* +X1924050Y-1365885D1* +X1924050Y-1371600D2* +X1924050Y-1367409D1* +G75* +G01X1924374Y-1364644D2* +G03X1924050Y-1365885I2216J-1241D1* +G74* +X1927405Y-1359230D2* +X1924374Y-1364644D1* +X1927468Y-1359120D2* +X1927405Y-1359230D1* +X1936750Y-1342898D2* +X1927468Y-1359120D1* +X1936750Y-1339850D2* +X1936750Y-1342898D1* +X1949450Y-1367409D2* +X1949450Y-1365885D1* +X1949450Y-1371600D2* +X1949450Y-1367409D1* +G75* +G01X1950812Y-1363635D2* +G03X1949450Y-1365885I1178J-2250D1* +G74* +X1968232Y-1354515D2* +X1950812Y-1363635D1* +G75* +G01X1968232Y-1354515D2* +G03X1968920Y-1354128I-6082J11617D1* +G74* +X1987550Y-1342898D2* +X1968920Y-1354128D1* +X1987550Y-1339850D2* +X1987550Y-1342898D1* +X1963166Y-1434116D2* +X1964690Y-1434116D1* +X1962150Y-1435100D2* +X1963166Y-1434116D1* +X1983740Y-1434116D2* +X1964690Y-1434116D1* +X1985264Y-1434116D2* +X1983740Y-1434116D1* +X1991360Y-1430020D2* +X1985264Y-1434116D1* +X2368550Y-1430909D2* +X2368550Y-1429385D1* +X2368550Y-1435100D2* +X2368550Y-1430909D1* +G75* +G01X2368550Y-1429385D2* +G03X2365950Y-1417614I-27940J0D1* +G74* +X2355802Y-1395769D2* +X2365950Y-1417614D1* +G75* +G01X2355802Y-1395769D2* +G03X2339520Y-1380452I-27257J-12661D1* +G74* +X2339398Y-1380404D2* +X2339520Y-1380452D1* +G75* +G01X2338811Y-1380103D2* +G03X2339398Y-1380404I1799J2788D1* +G74* +X2298026Y-1353782D2* +X2338811Y-1380103D1* +G75* +G01X2292096Y-1342898D2* +G03X2298026Y-1353782I12954J0D1* +G74* +X2292096Y-1336802D2* +X2292096Y-1342898D1* +G75* +G01X2292112Y-1336162D2* +G03X2292096Y-1336802I12938J-640D1* +G74* +X2292249Y-1333385D2* +X2292112Y-1336162D1* +G75* +G01X2292249Y-1333385D2* +G03X2292255Y-1333151I-4725J234D1* +G74* +X2292255Y-1328420D2* +X2292255Y-1333151D1* +G75* +G01X2292255Y-1328420D2* +G03X2288391Y-1323769I-4731J0D1* +G74* +X2241506Y-1315030D2* +X2288391Y-1323769D1* +G75* +G01X2241506Y-1315030D2* +G03X2239010Y-1314799I-2496J-13390D1* +G74* +X2218690Y-1314799D2* +X2239010Y-1314799D1* +G75* +G01X2218690Y-1314799D2* +G03X2211879Y-1316624I0J-13621D1* +G74* +X2198544Y-1324323D2* +X2211879Y-1316624D1* +G75* +G01X2198544Y-1324323D2* +G03X2196179Y-1328420I2366J-4097D1* +G74* +X2196179Y-1329944D2* +X2196179Y-1328420D1* +X2190750Y-1336040D2* +X2196179Y-1329944D1* +X1936750Y-1439291D2* +X1936750Y-1440815D1* +X1936750Y-1435100D2* +X1936750Y-1439291D1* +G75* +G01X1936750Y-1440815D2* +G03X1938560Y-1443248I2540J0D1* +G74* +X1945550Y-1445346D2* +X1938560Y-1443248D1* +G75* +G01X1945550Y-1445346D2* +G03X1946728Y-1445543I1360J4531D1* +G74* +X2161137Y-1453783D2* +X1946728Y-1445543D1* +G75* +G01X2161137Y-1453783D2* +G03X2162099Y-1453801I962J25033D1* +G74* +X2261870Y-1453801D2* +X2162099Y-1453801D1* +X2263394Y-1453801D2* +X2261870Y-1453801D1* +X2272030Y-1451610D2* +X2263394Y-1453801D1* +X2406650Y-1439291D2* +X2406650Y-1440815D1* +X2406650Y-1435100D2* +X2406650Y-1439291D1* +G75* +G01X2391400Y-1465707D2* +G03X2406650Y-1440815I-12690J24892D1* +G74* +X2385352Y-1468790D2* +X2391400Y-1465707D1* +G75* +G01X2371090Y-1472216D2* +G03X2385352Y-1468790I0J31401D1* +G74* +X2366010Y-1472216D2* +X2371090Y-1472216D1* +G75* +G01X2359209Y-1471471D2* +G03X2366010Y-1472216I6801J30656D1* +G74* +X2283215Y-1454611D2* +X2359209Y-1471471D1* +G75* +G01X2283215Y-1454611D2* +G03X2282190Y-1454499I-1025J-4619D1* +G74* +X2280666Y-1454499D2* +X2282190Y-1454499D1* +X2272030Y-1451610D2* +X2280666Y-1454499D1* +X2197100Y-1422400D2* +X2197100Y-1416050D1* +X2196180Y-1376791D2* +X2197100Y-1416050D1* +G75* +G01X2196179Y-1376680D2* +G03X2196180Y-1376791I4731J0D1* +G74* +X2196179Y-1375156D2* +X2196179Y-1376680D1* +X2190750Y-1369060D2* +X2196179Y-1375156D1* +X2127098Y-1422400D2* +X2127098Y-1428750D1* +X2154637Y-1443085D2* +X2127098Y-1428750D1* +G75* +G01X2154637Y-1443085D2* +G03X2162099Y-1444911I7462J14335D1* +G74* +X2232101Y-1444911D2* +X2162099Y-1444911D1* +G75* +G01X2232101Y-1444911D2* +G03X2244343Y-1439300I0J16161D1* +G74* +X2258286Y-1423121D2* +X2244343Y-1439300D1* +G75* +G01X2261870Y-1421479D2* +G03X2258286Y-1423121I0J-4731D1* +G74* +X2263394Y-1421479D2* +X2261870Y-1421479D1* +X2272030Y-1418590D2* +X2263394Y-1421479D1* +X2115134Y-1174750D2* +X2115134Y-1181100D1* +X2012950Y-1336802D2* +X2115134Y-1181100D1* +X2012950Y-1339850D2* +X2012950Y-1336802D1* +X2012950Y-1342898D2* +X1982470Y-1376426D1* +X2012950Y-1339850D2* +X2012950Y-1342898D1* +X2489784Y-1174750D2* +X2489784Y-1181100D1* +X2495923Y-1259579D2* +X2489784Y-1181100D1* +G75* +G01X2495963Y-1260602D2* +G03X2495923Y-1259579I-13113J0D1* +G74* +X2495963Y-1266698D2* +X2495963Y-1260602D1* +G75* +G01X2495732Y-1269151D2* +G03X2495963Y-1266698I-12882J2453D1* +G74* +X2482850Y-1336802D2* +X2495732Y-1269151D1* +X2482850Y-1339850D2* +X2482850Y-1336802D1* +X1911350Y-1430909D2* +X1911350Y-1429385D1* +X1911350Y-1435100D2* +X1911350Y-1430909D1* +G75* +G01X1911394Y-1428916D2* +G03X1911350Y-1429385I2496J-469D1* +G74* +X1912086Y-1425231D2* +X1911394Y-1428916D1* +G75* +G01X1920235Y-1411738D2* +G03X1912086Y-1425231I13975J-17647D1* +G74* +X1961187Y-1379306D2* +X1920235Y-1411738D1* +G75* +G01X1961187Y-1379306D2* +G03X1962150Y-1377315I-1577J1991D1* +G74* +X1962150Y-1375791D2* +X1962150Y-1377315D1* +X1962150Y-1371600D2* +X1962150Y-1375791D1* +X1965718Y-1372697D2* +X1982470Y-1376426D1* +G75* +G01X1965718Y-1372697D2* +G03X1964690Y-1372584I-1028J-4618D1* +G74* +X1963166Y-1372584D2* +X1964690Y-1372584D1* +X1962150Y-1371600D2* +X1963166Y-1372584D1* +X2381250Y-1430909D2* +X2381250Y-1429385D1* +X2381250Y-1435100D2* +X2381250Y-1430909D1* +G75* +G01X2382009Y-1427574D2* +G03X2381250Y-1429385I1781J-1811D1* +G74* +X2431291Y-1379126D2* +X2382009Y-1427574D1* +G75* +G01X2431291Y-1379126D2* +G03X2432050Y-1377315I-1781J1811D1* +G74* +X2432050Y-1375791D2* +X2432050Y-1377315D1* +X2432050Y-1371600D2* +X2432050Y-1375791D1* +X2482850Y-1339850D2* +X2482850Y-1342898D1* +X2464220Y-1354128D2* +X2482850Y-1342898D1* +G75* +G01X2464041Y-1354234D2* +G03X2464220Y-1354128I-6591J11336D1* +G74* +X2436968Y-1369975D2* +X2464041Y-1354234D1* +G75* +G01X2434590Y-1370616D2* +G03X2436968Y-1369975I0J4731D1* +G74* +X2433066Y-1370616D2* +X2434590Y-1370616D1* +X2432050Y-1371600D2* +X2433066Y-1370616D1* +X2115134Y-1174750D2* +X2115134Y-1168400D1* +X2170422Y-1152843D2* +X2115134Y-1168400D1* +G75* +G01X2174799Y-1152239D2* +G03X2170422Y-1152843I0J-16161D1* +G74* +X2454783Y-1152239D2* +X2174799Y-1152239D1* +G75* +G01X2462245Y-1154065D2* +G03X2454783Y-1152239I-7462J-14335D1* +G74* +X2489784Y-1168400D2* +X2462245Y-1154065D1* +X2489784Y-1174750D2* +X2489784Y-1168400D1* +X2092096Y-1422400D2* +X2092096Y-1416050D1* +X2096392Y-1377200D2* +X2092096Y-1416050D1* +G75* +G01X2096392Y-1377200D2* +G03X2096421Y-1376680I-4702J520D1* +G74* +X2096421Y-1375156D2* +X2096421Y-1376680D1* +X2101850Y-1369060D2* +X2096421Y-1375156D1* +X2381250Y-1439291D2* +X2381250Y-1440815D1* +X2381250Y-1435100D2* +X2381250Y-1439291D1* +G75* +G01X2379440Y-1443248D2* +G03X2381250Y-1440815I-730J2433D1* +G74* +X2372450Y-1445346D2* +X2379440Y-1443248D1* +G75* +G01X2371090Y-1445546D2* +G03X2372450Y-1445346I0J4731D1* +G74* +X2368550Y-1445546D2* +X2371090Y-1445546D1* +G75* +G01X2366835Y-1445224D2* +G03X2368550Y-1445546I1715J4409D1* +G74* +X2364628Y-1444366D2* +X2366835Y-1445224D1* +G75* +G01X2362200Y-1440815D2* +G03X2364628Y-1444366I3810J0D1* +G74* +X2362200Y-1429385D2* +X2362200Y-1440815D1* +G75* +G01X2362200Y-1429385D2* +G03X2360110Y-1420710I-19050J0D1* +G74* +X2348587Y-1398179D2* +X2360110Y-1420710D1* +G75* +G01X2348587Y-1398179D2* +G03X2342670Y-1390902I-20042J-10251D1* +G74* +X2340499Y-1389152D2* +X2342670Y-1390902D1* +G75* +G01X2340499Y-1389152D2* +G03X2328545Y-1384935I-11954J-14833D1* +G74* +X2327021Y-1384935D2* +X2328545Y-1384935D1* +X2321560Y-1384935D2* +X2327021Y-1384935D1* +X1983771Y-1380228D2* +X1982470Y-1376426D1* +G75* +G01X1984026Y-1381760D2* +G03X1983771Y-1380228I-4731J0D1* +G74* +X1984026Y-1383284D2* +X1984026Y-1381760D1* +X1986280Y-1386205D2* +X1984026Y-1383284D1* +G54D19* +X2279650Y-1260602D2* +X2279650Y-1266698D1* +X2305050Y-1260602D2* +X2305050Y-1266698D1* +X2330450Y-1260602D2* +X2330450Y-1266698D1* +X2355850Y-1260602D2* +X2355850Y-1266698D1* +X2381250Y-1260602D2* +X2381250Y-1266698D1* +X2406650Y-1260602D2* +X2406650Y-1266698D1* +X2432050Y-1260602D2* +X2432050Y-1266698D1* +X2457450Y-1260602D2* +X2457450Y-1266698D1* +X2482850Y-1260602D2* +X2482850Y-1266698D1* +X2482850Y-1336802D2* +X2482850Y-1342898D1* +X2457450Y-1336802D2* +X2457450Y-1342898D1* +X2432050Y-1336802D2* +X2432050Y-1342898D1* +X2406650Y-1336802D2* +X2406650Y-1342898D1* +X2381250Y-1336802D2* +X2381250Y-1342898D1* +X2355850Y-1336802D2* +X2355850Y-1342898D1* +X2330450Y-1336802D2* +X2330450Y-1342898D1* +X2305050Y-1336802D2* +X2305050Y-1342898D1* +X1809750Y-1260602D2* +X1809750Y-1266698D1* +X1835150Y-1260602D2* +X1835150Y-1266698D1* +X1860550Y-1260602D2* +X1860550Y-1266698D1* +X1885950Y-1260602D2* +X1885950Y-1266698D1* +X1911350Y-1260602D2* +X1911350Y-1266698D1* +X1936750Y-1260602D2* +X1936750Y-1266698D1* +X1962150Y-1260602D2* +X1962150Y-1266698D1* +X1987550Y-1260602D2* +X1987550Y-1266698D1* +X2012950Y-1260602D2* +X2012950Y-1266698D1* +X2012950Y-1336802D2* +X2012950Y-1342898D1* +X1987550Y-1336802D2* +X1987550Y-1342898D1* +X1962150Y-1336802D2* +X1962150Y-1342898D1* +X1936750Y-1336802D2* +X1936750Y-1342898D1* +X1911350Y-1336802D2* +X1911350Y-1342898D1* +X1885950Y-1336802D2* +X1885950Y-1342898D1* +X1860550Y-1336802D2* +X1860550Y-1342898D1* +X1835150Y-1336802D2* +X1835150Y-1342898D1* +G54D22* +X2162099Y-1428750D2* +X2162099Y-1416050D1* +X2197100Y-1428750D2* +X2197100Y-1416050D1* +X2232101Y-1428750D2* +X2232101Y-1416050D1* +X2127098Y-1428750D2* +X2127098Y-1416050D1* +X2057095Y-1428750D2* +X2057095Y-1416050D1* +X2092096Y-1428750D2* +X2092096Y-1416050D1* +X2244801Y-1168400D2* +X2244801Y-1181100D1* +X2209800Y-1168400D2* +X2209800Y-1181100D1* +X2174799Y-1168400D2* +X2174799Y-1181100D1* +X2279802Y-1168400D2* +X2279802Y-1181100D1* +X2314804Y-1168400D2* +X2314804Y-1181100D1* +X2489784Y-1168400D2* +X2489784Y-1181100D1* +X2454783Y-1168400D2* +X2454783Y-1181100D1* +X2349779Y-1168400D2* +X2349779Y-1181100D1* +X2384781Y-1168400D2* +X2384781Y-1181100D1* +X2419782Y-1168400D2* +X2419782Y-1181100D1* +X1870151Y-1168400D2* +X1870151Y-1181100D1* +X1835150Y-1168400D2* +X1835150Y-1181100D1* +X1800149Y-1168400D2* +X1800149Y-1181100D1* +X1905152Y-1168400D2* +X1905152Y-1181100D1* +X1940154Y-1168400D2* +X1940154Y-1181100D1* +X2115134Y-1168400D2* +X2115134Y-1181100D1* +X2080133Y-1168400D2* +X2080133Y-1181100D1* +X1975129Y-1168400D2* +X1975129Y-1181100D1* +X2010131Y-1168400D2* +X2010131Y-1181100D1* +X2045132Y-1168400D2* +X2045132Y-1181100D1* +M02* diff --git a/gerbview/gerber_test_files/octogonal.gbr b/gerbview/gerber_test_files/octogonal.gbr new file mode 100644 index 0000000..909872d --- /dev/null +++ b/gerbview/gerber_test_files/octogonal.gbr @@ -0,0 +1,27 @@ +* +%FSLAX26Y26*% +%MOIN*% +G04 A4 - i274x.oc8.d36 * +%AMA4top* +4,1,8, +0.034500,0.014290, +0.034500,-0.014290, +0.014290,-0.034500, +-0.014290,-0.034500, +-0.034500,-0.014290, +-0.034500,0.014290, +-0.014290,0.034500, +0.014290,0.034500, +0.034500,0.014290, +0.0000* +% +%ADD40A4top*% +%IPPOS*% +%LNfp0149448top.gbx*% +%LPD*% +G75* +G54D40* +X04750000Y00344900D03* +X04856300Y00246400D03* +X04750000Y00148000D03* +M02* diff --git a/gerbview/gerber_test_files/test-aperture-polygon-flash.gbr b/gerbview/gerber_test_files/test-aperture-polygon-flash.gbr new file mode 100644 index 0000000..788a755 --- /dev/null +++ b/gerbview/gerber_test_files/test-aperture-polygon-flash.gbr @@ -0,0 +1,27 @@ +G04 Test flashing of polygon apertures* +G04 Four groups of polygon apertures are arranged in a square* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ADD10P,0.050X3*% +%ADD11P,0.050X6X-45X0.035*% +%ADD12P,0.040X10X25X0.025X0.025X0.0150*% + +G04 Triangle, centered at 0,0 * +G54D10* +X0Y0D03* + +G04 Hexagon with round hole rotate 45 degreed ccwise, centered at 0.1,0 * +G54D11* +X00100Y0D03* + +G04 10-sided with square hole rotated 25 degrees, centered at 0,0.1 * +G54D12* +X0Y00100D03* + +G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 * +G54D11* +X00100Y00090D03* +X00100Y00110D03* + +M02* diff --git a/gerbview/gerber_test_files/test-aperture-rectangle-flash-with_hole.gbr b/gerbview/gerber_test_files/test-aperture-rectangle-flash-with_hole.gbr new file mode 100644 index 0000000..8aeb79c --- /dev/null +++ b/gerbview/gerber_test_files/test-aperture-rectangle-flash-with_hole.gbr @@ -0,0 +1,27 @@ +G04 Test flashing of rectangular apertures* +G04 Four groups of rectangular apertures are arranged in a square* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ADD10R,0.050X0.080*% +%ADD11R,0.080X0.050X0.025*% +%ADD12R,0.050X0.025X0.025X0.0150*% + +G04 No hole, centered at 0,0 * +G54D10* +X0Y0D03* + +G04 Round hole, centered at 0.1,0 * +G54D11* +X00100Y0D03* + +G04 Square hole, centered at 0,0.1 * +G54D12* +X0Y00100D03* + +G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 * +G54D11* +X00100Y00090D03* +X00100Y00110D03* + +M02* diff --git a/gerbview/gerber_test_files/test-image-justify-with-offset.gbr b/gerbview/gerber_test_files/test-image-justify-with-offset.gbr new file mode 100644 index 0000000..6e71d62 --- /dev/null +++ b/gerbview/gerber_test_files/test-image-justify-with-offset.gbr @@ -0,0 +1,19 @@ +G04 Test image justify 1* +G04 Crosshairs should be justified to the X axis * +G04 and 0.5 inches offset from Y axis * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%IJB.5*% +%ADD10C,0.050*% + +G04 Crosshairs * +X-1000Y0D02* +G54D10* +X1000Y0D01* + +X0Y-1000D02* +G54D10* +X0Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-image-offset.gbr b/gerbview/gerber_test_files/test-image-offset.gbr new file mode 100644 index 0000000..11242cf --- /dev/null +++ b/gerbview/gerber_test_files/test-image-offset.gbr @@ -0,0 +1,18 @@ +G04 Test image offset * +G04 Crosshairs should be centered on 0,0 in final rendering* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%IOA-2.0B-1.0*% +%ADD10C,0.050*% + +G04 Crosshairs to be on 0,0 * +X1000Y1000D02* +G54D10* +X3000Y1000D01* + +X2000Y0D02* +G54D10* +X2000Y2000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-image-polarity.gbr b/gerbview/gerber_test_files/test-image-polarity.gbr new file mode 100644 index 0000000..e012966 --- /dev/null +++ b/gerbview/gerber_test_files/test-image-polarity.gbr @@ -0,0 +1,17 @@ +G04 Test image polarity * +G04 Crosshairs should be cut out of a positive background* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%IPNEG*% +%ADD10C,0.050*% + +G04 Draw crosshairs * +X-1000Y0D02* +G54D10* +X1000Y0D01* +X0Y-1000D02* +G54D10* +X0Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-image-rotation.gbr b/gerbview/gerber_test_files/test-image-rotation.gbr new file mode 100644 index 0000000..c136b5b --- /dev/null +++ b/gerbview/gerber_test_files/test-image-rotation.gbr @@ -0,0 +1,21 @@ +G04 Test image rotation * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%IR270*% +%ADD10C,0.050*% + +G04 Quarter star * +X1000Y0D02* +G54D10* +X2000Y0D01* + +X1000Y0D02* +G54D10* +X2000Y1000D01* + +X1000Y0D02* +G54D10* +X1000Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-axis-select.gbr b/gerbview/gerber_test_files/test-layer-axis-select.gbr new file mode 100644 index 0000000..d5f003e --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-axis-select.gbr @@ -0,0 +1,15 @@ +G04 Test layer axis select * +G04 Line is drawn along A axis, then axis select switches it and renders * +G04 line along y axis * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ASAYBX*% +%ADD10C,0.050*% + +G04 Draw line * +X-1000Y0D02* +G54D10* +X1000Y0D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr b/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr new file mode 100644 index 0000000..95b8555 --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr @@ -0,0 +1,68 @@ +G04 Test handling of unit changes within a RS274X file * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +G04 Aperture 10 should be in Inches * +%ADD10C,0.050*% +%MOMM*% +G04 Aperture 11 should be in MMs * +%ADD11C,1.250*% +G04 Aperture 12 should be in MMs * +%AMTHERMAL* +7,0,0,25.4,12.7,2.54,0*% +%MOIN*% +G04 Aperture 13 is in inches * +%AMTHERMALTWO* +7,0,0,1,0.5,0.1,0*% +%MOMM*% +%ADD12THERMAL*% +%MOIN*% +%ADD13THERMALTWO*% + +%MOIN*% +G04 Box 1, using aperture 10* +X0Y0D02* +G54D10* +X0Y0D01* +X1000D01* +Y1000D01* +X0D01* +Y0D01* + +G04 Box 2, using aperture 11* +X2000Y0D02* +G54D11* +X2000Y0D01* +X3000D01* +Y1000D01* +X2000D01* +Y0D01* + +%MOMM*% +G04 Box 3, using aperture 10* +X100000Y0D02* +G54D10* +X100000Y0D01* +X125000D01* +Y25000D01* +X100000D01* +Y0D01* + +G04 Draw Thermal in box 1* +G54D12* +Y12000X12700D03* + +G04 Draw Thermal in box 2* +G04 ..switch to inches for coordinates* +G70* +Y500X2500D02* +G54D12* +Y500X2500D03* + +G04 ..switch to mms for coordinates* +G71* +G04 Draw Thermal in box 3* +G54D13* +Y12000X112000D03* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-rotation.gbr b/gerbview/gerber_test_files/test-layer-rotation.gbr new file mode 100644 index 0000000..1c3696a --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-rotation.gbr @@ -0,0 +1,23 @@ +G04 Test layer rotation 1 * +G04 Quarter star should be rotated 45 degrees counterclockwise, pointing* +G04 the center line straight up * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%RO45.0*% +%ADD10C,0.025*% + +G04 Quarter star * +X1000Y0D02* +G54D10* +X2000Y0D01* + +X1000Y0D02* +G54D10* +X2000Y1000D01* + +X1000Y0D02* +G54D10* +X1000Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-scale-factor.gbr b/gerbview/gerber_test_files/test-layer-scale-factor.gbr new file mode 100644 index 0000000..02a7b7d --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-scale-factor.gbr @@ -0,0 +1,17 @@ +G04 Test layer scale factor 1 * +G04 Crosshairs should be centered on 0,0 and 2 inches wide and 1 inch tall* +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%SFA2B1*% +%ADD10C,0.025*% + +G04 Crosshairs to be on 0,0 * +X-500Y0D02* +G54D10* +X500Y0D01* +X0Y-500D02* +G54D10* +X0Y500D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr b/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr new file mode 100644 index 0000000..4f69391 --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr @@ -0,0 +1,17 @@ +G04 Test step and repeat 1* +G04 Repeat a crosshair 3 times in the x direction and 2 times in the Y * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%SRX3Y2I5.0J2*% +%ADD10C,0.050*% + +G04 Draw crosshairs * +X-1000Y0D02* +G54D10* +X1000Y0D01* +X0Y-1000D02* +G54D10* +X0Y1000D01* + +M02* diff --git a/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr b/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr new file mode 100644 index 0000000..392036f --- /dev/null +++ b/gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr @@ -0,0 +1,18 @@ +G04 Test step and repeat 1* +G04 Repeat a crosshair 3 times in the x direction and 2 times in the Y * +G04 Handcoded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%SRX3Y2I1J1*% +%ADD10C,0.050*% + +G04 Draw a simple square* +G36* +G01X00400Y0D02* +X00600Y0D01* +X00600Y00200D01* +X00400Y00200D01* +X00400Y0D01* +G37* + +M02* diff --git a/gerbview/gerber_test_files/test-polygon_with_arc-fill.gbr b/gerbview/gerber_test_files/test-polygon_with_arc-fill.gbr new file mode 100644 index 0000000..4f08394 --- /dev/null +++ b/gerbview/gerber_test_files/test-polygon_with_arc-fill.gbr @@ -0,0 +1,18 @@ +G04 Draw a rectangle with a rounded right side +G04 Hand coded by Julian Lamb * +%MOIN*% +%FSLAX23Y23*% +%ADD10C,0.050*% + +G04 Draw a rectangle with a rounded right side* +G36* +G01X0Y0D02* +X00200Y0D01* +G75* +G03X00200Y00200I0J00100D01* +G01X0Y00200D01* +G04 Do not close with a final line, so let gerbv automatically close* +G37* + + +M02* diff --git a/gerbview/gerber_test_files/test2_line_with_rect_aperture.gbr b/gerbview/gerber_test_files/test2_line_with_rect_aperture.gbr new file mode 100644 index 0000000..26c0735 --- /dev/null +++ b/gerbview/gerber_test_files/test2_line_with_rect_aperture.gbr @@ -0,0 +1,67 @@ +G04 start of page 2 for group 0 idx 0 +G04 Title: (unknown), component * +G04 Creator: pcb 20080202 * +G04 CreationDate: Sat 27 Feb 2010 07:29:32 PM GMT UTC * +G04 For: randomplague * +G04 Format: Gerber/RS-274X * +G04 PCB-Dimensions: 70000 45000 * +G04 PCB-Coordinate-Origin: lower left * +%MOIN*% +%FSLAX24Y24*% +%LNFRONT*% +%ADD11C,0.0200*% +%ADD12C,0.0600*% +%ADD13R,0.0200X0.0200*% +%ADD14R,0.0512X0.0512*% +%ADD15C,0.0380*% +G54D11*X1900Y1250D02*X1250D01* +X1900Y750D02*X750D01* +X2550D02*X3250D01* +X1250Y1250D02*X750Y1750D01* +X1900Y2250D02*Y2600D01* +X750Y3750D01* +X1000Y2750D02*X750D01* +X1000D02*X1500Y2250D01* +Y1750D02*X1900D01* +X1500D02*Y2250D01* +X3250Y750D02*Y3069D01* +X5750Y3750D02*X4000D01* +X4600Y2250D02*Y2900D01* +X4000Y3500D01* +X3250Y3069D02*X2819Y3500D01* +X4600Y750D02*X5750D01* +X4600Y1250D02*X5250D01* +X5750Y1750D01* +X4600D02*X5000D01* +X5750Y2750D02*X5250Y2250D01* +X5000Y2000D02*Y1750D01* +Y2000D02*X5250Y2250D01* +G54D11*G36* +X5450Y4050D02*Y3450D01* +X6050D01* +Y4050D01* +X5450D01* +G37* +G54D12*X5750Y2750D03* +Y1750D03* +G54D11*G36* +X450Y4050D02*Y3450D01* +X1050D01* +Y4050D01* +X450D01* +G37* +G54D12*X750Y2750D03* +Y1750D03* +Y750D03* +X5750D03* +G54D13*X3950D02*X4600D01* +X3950Y1250D02*X4600D01* +X3950Y1750D02*X4600D01* +X1900Y2250D02*X2550D01* +X1900Y1750D02*X2550D01* +X1900Y1250D02*X2550D01* +X1900Y750D02*X2550D01* +X3950Y2250D02*X4600D01* +G54D14*X2819Y4051D02*Y3500D01* +X4000Y4051D02*Y3500D01* +G54D15*M02* diff --git a/gerbview/gerber_test_files/test_line_with_rect_aperture.gbr b/gerbview/gerber_test_files/test_line_with_rect_aperture.gbr new file mode 100644 index 0000000..b93e1c9 --- /dev/null +++ b/gerbview/gerber_test_files/test_line_with_rect_aperture.gbr @@ -0,0 +1,16 @@ +* +%FSLAX23Y23*% +%MOIN*% +%ADD10R,0.025X0.025*% +%ADD11R,0.03X0.06*% +%IPPOS*% +%LNtest_rect.gbr*% +%LPD*% +G75* +G54D10* +X04000Y00100D02* +X04400Y00140D01* +G54D11* +X03000Y00100D02* +X02400Y-00340D01* +M02* diff --git a/gerbview/gerber_test_files/test_polygons_with_arcs.gbr b/gerbview/gerber_test_files/test_polygons_with_arcs.gbr new file mode 100644 index 0000000..3dc7927 --- /dev/null +++ b/gerbview/gerber_test_files/test_polygons_with_arcs.gbr @@ -0,0 +1,4163 @@ +* +%FSLAX35Y35*% +%MOMM*% +%ADD10C,0.085000*% +%ADD11C,1.000000*% +%IPPOS*% +%LNl2p*% +%LPD*% +%SRX1Y1I0J0*% +G01* +G75* +G36* +X-824649Y824737D02* +X-824642Y824746D01* +X-824637Y824748D01* +X-600285Y824596D01* +G02X-596337Y813997I0J-6035D01* +G01X-596759Y813502D01* +X-599070Y812402D01* +X-599079Y812403D01* +X-600633Y812842D01* +G03X-591714Y760887I-18257J-29877D01* +G01X-589396Y761987D01* +X-587850Y761553D01* +G03X-543350Y814584I18275J29851D01* +G02X-538846Y824554I4504J3968D01* +G01X-387906Y824445D01* +X-387901Y824439D01* +X-387898Y718310D01* +X-387892Y718296D01* +X-387887Y718290D01* +X-337968Y678268D01* +X-337966Y678263D01* +X-337746Y625972D01* +G02X-347743Y621473I-6001J-23D01* +G03X-394478Y621365I-23307J-26119D01* +G02X-402955Y621809I-4016J4477D01* +G01X-407368Y626784D01* +X-409076Y628288D01* +G02X-406164Y638849I3817J4630D01* +G03X-421754Y706900I-5285J34600D01* +G01X-699601D01* +G03X-766967Y720229I-35002J0D01* +G02X-771614Y718929I-2844J1211D01* +G03X-817118Y687087I-10523J-33398D01* +G03X-817151Y685566I34972J-1522D01* +G01X-823562D01* +X-824649Y824737D01* +G37* +G36* +X-823562Y685566D02* +X-817151D01* +G03X-749783Y672221I35006J0D01* +G02X-745135Y673521I2845J-1211D01* +G03X-699601Y706900I10532J33379D01* +G01X-421754D01* +G03X-433713Y646441I10305J-33451D01* +G02X-436626Y635881I-3821J-4628D01* +G03X-407912Y575275I5286J-34601D01* +G02X-399435Y574831I4016J-4476D01* +G01X-397154Y572042D01* +G03X-379243Y561250I26239J23289D01* +G01X-379141Y529918D01* +X-474048D01* +G03X-543414Y536656I-35010J0D01* +G02X-546852Y534512I-2891J807D01* +G03X-587886Y505152I-6401J-34409D01* +G01X-601503D01* +G03X-668659Y518983I-35003J0D01* +G02X-670664Y517431I-2675J1384D01* +G02X-673622Y517895I52J9992D01* +G03X-695002Y516777I-8947J-33885D01* +G02X-702296Y520311I-1717J5751D01* +G03X-767799Y519300I-32561J-12864D01* +G03X-812330Y488561I-9647J-33650D01* +G03X-812451Y485651I34887J-2910D01* +G01X-822000D01* +X-823562Y685566D01* +G37* +G36* +X-822000Y485651D02* +X-812451D01* +G03X-744501Y473801I35009J0D01* +G03X-722388Y474726I9666J33715D01* +G02X-715313Y471655I1713J-5739D01* +G03X-650391Y470217I32751J12389D01* +G02X-646837Y471709I2656J-1348D01* +G03X-601872Y500077I10332J33443D01* +G01X-588255D01* +G03X-518896Y493354I35005J0D01* +G02X-515458Y495498I2890J-806D01* +G03X-474048Y529918I6400J34420D01* +G01X-379141D01* +X-378950Y471399D01* +X-379636Y414481D01* +G02X-389468Y410485I-5958J566D01* +G03X-442629Y400682I-22547J-26775D01* +G01X-523620D01* +G03X-584299Y424470I-35002J0D01* +G02X-586947Y423652I-2113J2146D01* +G02X-589302Y424942I3781J9697D01* +G03X-643324Y397426I-19082J-29325D01* +G03X-643372Y395592I34957J-1835D01* +G01X-821296D01* +X-822000Y485651D01* +G37* +G36* +X-821296Y395592D02* +X-643372D01* +G03X-582690Y371800I35005J0D01* +G02X-580043Y372618I2111J-2139D01* +G02X-577688Y371328I-3780J-9695D01* +G03X-523620Y400682I19066J29354D01* +G01X-442629D01* +G03X-426828Y351995I30614J-16972D01* +G03X-380460Y368307I14887J31742D01* +G01X-336608Y352876D01* +X-336605Y352871D01* +X-336565Y345194D01* +X-336559Y345186D01* +X-336549Y345178D01* +X-299824Y332640D01* +X-299819Y332634D01* +X-293878Y306411D01* +X-296682Y299910D01* +X-367926D01* +X-368938Y308267D01* +X-371917Y316141D01* +X-376689Y323076D01* +X-382979Y328670D01* +X-390423Y332602D01* +X-398590Y334642D01* +X-402810Y334912D01* +X-411164Y333871D01* +X-419027Y330866D01* +X-425946Y326071D01* +X-431520Y319762D01* +X-435426Y312305D01* +X-437438Y304130D01* +X-437694Y299910D01* +X-585657D01* +G03X-635902Y285301I-18631J-29633D01* +G01X-651700D01* +G03X-672543Y317315I-35008J0D01* +G02X-674177Y319553I1344J2696D01* +G02X-673724Y322193I11767J-660D01* +G03X-742595Y333161I-33957J8489D01* +G03X-742682Y330692I34923J-2469D01* +G01X-820789D01* +X-821296Y395592D01* +G37* +G36* +X-820789Y330692D02* +X-742682D01* +G03X-721837Y298675I35011J0D01* +G02X-720289Y295144I-1333J-2689D01* +G03X-710025Y259188I33599J-9852D01* +G02X-710457Y250354I-4231J-4221D01* +G03X-664764Y249541I22375J-26924D01* +G02X-664333Y258377I4263J4221D01* +G03X-655092Y270269I-22375J26924D01* +G01X-639292D01* +G03X-624463Y241657I35017J0D01* +G02X-623734Y237872I-1897J-2328D01* +G03X-558138Y220849I30589J-17023D01* +G01X-440238D01* +G03X-426462Y195115I34899J2128D01* +G02X-426268Y186271I-3929J-4510D01* +G03X-367037Y161005I24227J-25266D01* +G01X-348730D01* +X-364649Y120947D01* +X-364653Y98350D01* +X-364656Y98344D01* +X-390753Y66602D01* +X-390758Y66601D01* +X-556452Y67300D01* +X-566659Y67028D01* +G02X-572057Y75947I-151J6002D01* +G03X-630900Y113652I-30522J17134D01* +G02X-640643Y113702I-4854J3525D01* +G03X-697256Y72485I-28550J-20274D01* +G02X-702251Y63415I-5153J-3073D01* +G01X-742203Y62348D01* +X-751941Y58383D01* +G02X-760167Y63303I-2249J5577D01* +G03X-810810Y90813I-34830J-3748D01* +G02X-818958Y96370I-2137J5619D01* +G01X-819253Y134021D01* +G02X-810377Y139331I6003J39D01* +G03X-767009Y192811I16774J30722D01* +G02X-766734Y200915I4559J3902D01* +G03X-810894Y254821I-24669J24832D01* +G02X-820235Y259759I-3343J4979D01* +G01X-820789Y330692D01* +G37* +G36* +X-655092Y270269D02* +G03X-651700Y285301I-31616J15032D01* +G01X-635902D01* +G03X-639131Y273619I31615J-15024D01* +G03X-639292Y270269I34856J-3351D01* +G01X-655092D01* +G37* +G36* +X-601872Y500077D02* +G03X-601503Y505152I-34633J5075D01* +G01X-587886D01* +G03X-588030Y504037I34633J-5049D01* +G03X-588255Y500077I34781J-3960D01* +G01X-601872D01* +G37* +G36* +X-585657Y299910D02* +X-437694D01* +X-436681Y291553D01* +X-433703Y283679D01* +X-428931Y276744D01* +X-422641Y271149D01* +X-415197Y267218D01* +X-407030Y265177D01* +X-402810Y264908D01* +X-394456Y265948D01* +X-386593Y268953D01* +X-379674Y273749D01* +X-374100Y280058D01* +X-370194Y287515D01* +X-368181Y295689D01* +X-367926Y299910D01* +X-296682D01* +X-307312Y275263D01* +X-308500Y273499D01* +X-310150Y269702D01* +X-337228Y232797D01* +X-337414Y206733D01* +X-342750Y176052D01* +X-348730Y161005D01* +X-367037D01* +G03X-380888Y188895I-35005J0D01* +G02X-381082Y197739I3958J4511D01* +G03X-440260Y224704I-24217J25272D01* +G03X-440303Y222976I34921J-1727D01* +G01X-558202D01* +G03X-572976Y249462I-34943J-2128D01* +G02X-573706Y253248I1902J2330D01* +G03X-585657Y299910I-30582J17029D01* +G37* +G36* +X-558202Y222976D02* +G01X-440303D01* +G03X-440238Y220849I34963J0D01* +G01X-558138D01* +G03X-558202Y222976I-35007J-0D01* +G37* +G36* +X-585361Y300069D02* +G01X-437853D01* +G02X-437853Y299751I0J-159D01* +G01X-585361D01* +G02X-585361Y300069I0J159D01* +G37* +G36* +X-367767D02* +G01X-296855D01* +G02X-296855Y299751I0J-159D01* +G01X-367767D01* +G02X-367767Y300069I0J159D01* +G37* +G36* +X-366878Y161164D02* +G01X-348900D01* +G02X-348900Y160846I0J-159D01* +G01X-366878D01* +G02X-366878Y161164I0J159D01* +G37* +G36* +X-558043Y223135D02* +G01X-440462D01* +G02X-440462Y222818I0J-159D01* +G01X-558043D01* +G02X-558043Y223135I0J159D01* +G37* +G36* +X-473889Y530077D02* +G01X-379299D01* +G02X-379299Y529759I0J-159D01* +G01X-473889D01* +G02X-473889Y530077I0J159D01* +G37* +G36* +X-601712Y500236D02* +G01X-588414D01* +G02X-588414Y499918I0J-159D01* +G01X-601712D01* +G02X-601712Y500236I0J159D01* +G37* +G36* +X-557979Y221007D02* +G01X-440397D01* +G02X-440397Y220690I0J-159D01* +G01X-557979D01* +G02X-557979Y221007I0J159D01* +G37* +G36* +X-654917Y270427D02* +G01X-639451D01* +G02X-639451Y270110I0J-159D01* +G01X-654917D01* +G02X-654917Y270427I0J159D01* +G37* +G36* +X-523461Y400841D02* +G01X-442811D01* +G02X-442811Y400523I0J-159D01* +G01X-523461D01* +G02X-523461Y400841I0J159D01* +G37* +G36* +X-821138Y395750D02* +G01X-643531D01* +G02X-643531Y395433I0J-159D01* +G01X-821138D01* +G02X-821138Y395750I0J159D01* +G37* +G36* +X-651541Y285460D02* +G01X-636078D01* +G02X-636078Y285142I0J-159D01* +G01X-651541D01* +G02X-651541Y285460I0J159D01* +G37* +G36* +X-820631Y330851D02* +G01X-742841D01* +G02X-742841Y330533I0J-159D01* +G01X-820631D01* +G02X-820631Y330851I0J159D01* +G37* +G36* +X-601344Y505310D02* +G01X-588046D01* +G02X-588046Y504993I0J-159D01* +G01X-601344D01* +G02X-601344Y505310I0J159D01* +G37* +G36* +X-821841Y485810D02* +G01X-812610D01* +G02X-812610Y485492I0J-159D01* +G01X-821841D01* +G02X-821841Y485810I0J159D01* +G37* +G36* +X-699443Y707059D02* +G01X-422282D01* +G02X-422282Y706741I0J-159D01* +G01X-699443D01* +G02X-699443Y707059I0J159D01* +G37* +G36* +X-823403Y685724D02* +G01X-817310D01* +G02X-817310Y685407I0J-159D01* +G01X-823403D01* +G02X-823403Y685724I0J159D01* +G37* +G36* +X-817138Y-494161D02* +G01X-817137Y-492155D01* +G02X-809582Y-486361I6005J-7D01* +G03X-809561Y-420931I12532J32711D01* +G02X-817119Y-415136I-1559J5794D01* +G01X-817115Y-399500D01* +X-762202D01* +X-761190Y-407857D01* +X-758211Y-415731D01* +X-753439Y-422666D01* +X-747149Y-428260D01* +X-739705Y-432192D01* +X-731538Y-434232D01* +X-727200Y-434502D01* +X-718843Y-433490D01* +X-710969Y-430511D01* +X-704034Y-425739D01* +X-698439Y-419449D01* +X-694508Y-412005D01* +X-692468Y-403838D01* +X-692198Y-399500D01* +X-678475D01* +X-678849Y-421921D01* +X-679243Y-427151D01* +X-692851Y-444036D01* +X-713002Y-463005D01* +X-724312Y-492342D01* +X-724320Y-492348D01* +X-739665Y-494000D01* +X-747006Y-494004D01* +X-764366Y-506933D01* +G03X-808184Y-499385I-26510J-22937D01* +G02X-817120Y-494631I-2955J5221D01* +G01X-817138Y-494161D01* +G37* +G36* +X-817115Y-399500D02* +X-817098Y-331697D01* +X-809495Y-320299D01* +X-784004Y-316501D01* +X-783996Y-316504D01* +X-769505Y-330645D01* +X-769492Y-330650D01* +X-766159Y-330772D01* +X-765403Y-331378D01* +X-752004Y-331277D01* +X-676050Y-334003D01* +X-678450Y-398000D01* +X-678475Y-399500D01* +X-692198D01* +X-693210Y-391143D01* +X-696189Y-383269D01* +X-700961Y-376334D01* +X-707251Y-370739D01* +X-714694Y-366808D01* +X-722862Y-364768D01* +X-727200Y-364498D01* +X-735557Y-365510D01* +X-743431Y-368489D01* +X-750365Y-373261D01* +X-755960Y-379551D01* +X-759892Y-386995D01* +X-761932Y-395162D01* +X-762202Y-399500D01* +X-817115D01* +G37* +G36* +X-816956Y-399341D02* +X-762361D01* +G02X-762361Y-399659I0J-159D01* +G01X-816956D01* +G02X-816956Y-399341I0J159D01* +G37* +G36* +X-692039D02* +G01X-678634D01* +G02X-678634Y-399659I0J-159D01* +G01X-692039D01* +G02X-692039Y-399341I0J159D01* +G37* +G36* +X-816000Y-16537D02* +G02X-816000Y-16535I5999J0D01* +G01Y-12898D01* +X-814047Y5549D01* +X-814044Y5553D01* +X-740047Y49549D01* +X-681904Y50748D01* +X-681900Y50746D01* +X-644297Y3204D01* +X-644290Y3201D01* +G02X-638532Y-5596I430J-6002D01* +G03X-576813Y-5213I30962J-16325D01* +G02X-571576Y3650I5283J2857D01* +G01X-422562Y4569D01* +G03X-364093Y4932I29115J19510D01* +G01X-339385Y5079D01* +G03X-325795Y-25183I35003J-2463D01* +G02X-325003Y-33927I-3650J-4739D01* +G03X-329352Y-74590I26059J-23351D01* +G02X-330354Y-81827I-5222J-2965D01* +G02X-333299Y-83767I-15176J19833D01* +G02X-337538Y-82630I-1589J2546D01* +G03X-401400Y-110856I-30914J-16415D01* +G02X-405567Y-118693I-5650J-2022D01* +G03X-431452Y-158328I8647J-33917D01* +G01X-660059D01* +G03X-670904Y-132990I-35021J0D01* +G03X-681631Y-83813I-29157J19398D01* +G02X-682874Y-75053I3367J4946D01* +G02X-680106Y-72964I9903J-10243D01* +G03X-717520Y-73348I-19011J29394D01* +G02X-718243Y-83693I-3386J-4961D01* +G03X-724217Y-138923I18206J-29907D01* +G03X-711494Y-189235I29134J-19397D01* +G02X-712604Y-200287I-2819J-5299D01* +G03X-737625Y-232041I9945J-33571D01* +G03X-737672Y-233854I34958J-1813D01* +G01X-766592D01* +G03X-770380Y-184011I-26324J23065D01* +G02X-772046Y-174462I2783J5405D01* +G03X-808728Y-117499I-25794J23682D01* +G02X-815995Y-111871I-1302J5825D01* +G01X-816000Y-111636D01* +Y-96062D01* +G02X-808537Y-90245I6000J-2D01* +G03X-808538Y-22355I8538J33945D01* +G02X-816000Y-16537I-1463J5819D01* +G37* +G36* +X-792630Y-293580D02* +G02X-792626Y-293372I6005J0D01* +G01X-457899D01* +G03X-393888Y-312989I35012J0D01* +G02X-383370Y-314553I4847J-3557D01* +G03X-318688Y-312229I31862J14487D01* +G02X-316297Y-310417I2756J-1153D01* +G02X-313968Y-310737I-621J-13151D01* +G03X-295478Y-309237I6516J34389D01* +G02X-288282Y-312970I1563J-5789D01* +G03X-242255Y-337205I33938J8630D01* +G02X-234386Y-343991I1986J-5652D01* +G03X-166973Y-362180I34398J-6533D01* +G01X366616D01* +X367628Y-370537D01* +X370607Y-378411D01* +X375379Y-385346D01* +X378138Y-387800D01* +X-378466D01* +X-379478Y-379443D01* +X-382457Y-371569D01* +X-387229Y-364634D01* +X-393519Y-359039D01* +X-400963Y-355108D01* +X-409130Y-353068D01* +X-413350Y-352798D01* +X-421704Y-353839D01* +X-429567Y-356844D01* +X-436486Y-361639D01* +X-440365Y-366030D01* +X-462486D01* +X-463498Y-357673D01* +X-466477Y-349799D01* +X-471249Y-342864D01* +X-477539Y-337269D01* +X-484983Y-333338D01* +X-493150Y-331298D01* +X-497370Y-331028D01* +X-505724Y-332069D01* +X-513587Y-335074D01* +X-520506Y-339869D01* +X-526079Y-346178D01* +X-529985Y-353635D01* +X-531998Y-361809D01* +X-532254Y-366030D01* +X-620995D01* +X-622653Y-320319D01* +X-622673Y-320300D01* +X-761902Y-321347D01* +X-761907Y-321344D01* +X-790414Y-298238D01* +G02X-792630Y-293580I3789J4658D01* +G37* +G36* +X-792626Y-293372D02* +G02X-788781Y-287975I6001J-208D01* +G03X-770460Y-237635I-11995J32869D01* +G03X-766592Y-233854I-22456J26846D01* +G01X-737672D01* +G03X-686256Y-202935I35005J0D01* +G02X-685639Y-192052I2818J5299D01* +G03X-660059Y-158328I-9440J33724D01* +G01X-431452D01* +G03X-420064Y-178869I34532J5717D01* +G02X-421075Y-188591I-3948J-4503D01* +G03X-380686Y-192791I17245J-30460D01* +G02X-379675Y-183069I3978J4500D01* +G03X-364125Y-140302I-17255J30484D01* +G02X-359803Y-132967I5807J1519D01* +G01X-354042Y-130950D01* +X-352193Y-130047D01* +G02X-344335Y-132155I2782J-5329D01* +G03X-282154Y-126204I29585J18710D01* +G02X-272599Y-123891I5588J-2190D01* +G03X-221681Y-124363I25682J23802D01* +G02X-212873Y-124541I4322J-4164D01* +G03X-211918Y-77027I26162J23241D01* +G02X-220727Y-76849I-4322J4169D01* +G03X-256432Y-66411I-26175J-23249D01* +G02X-264046Y-60146I-1635J5772D01* +G03X-277485Y-29617I-34892J2863D01* +G02X-278277Y-20873I3687J4742D01* +G01X-274616Y-15989D01* +G02X-264209Y-14639I5588J-2287D01* +G03X-219054Y-23880I27861J21199D01* +G02X-210538Y-26823I2961J-5224D01* +G03X-195446Y16880I32387J13273D01* +G02X-203962Y19823I-2961J5225D01* +G03X-205508Y23100I-32388J-13276D01* +G01X-32384D01* +X-31372Y14743D01* +X-28393Y6869D01* +X-23621Y-66D01* +X-17331Y-5661D01* +X-9887Y-9592D01* +X-1720Y-11632D01* +X2500Y-11902D01* +X10854Y-10861D01* +X18717Y-7856D01* +X25636Y-3061D01* +X31209Y3248D01* +X35116Y10705D01* +X37128Y18879D01* +X37384Y23100D01* +X174268D01* +G03X184282Y5427I34151J7678D01* +G02X184502Y-2281I-4484J-3985D01* +G03X178010Y-15450I27461J-21724D01* +G01X119784D01* +X118772Y-7093D01* +X115793Y781D01* +X111021Y7716D01* +X104731Y13311D01* +X97287Y17242D01* +X89120Y19282D01* +X84900Y19552D01* +X76546Y18511D01* +X68683Y15506D01* +X61764Y10711D01* +X56190Y4402D01* +X52284Y-3055D01* +X50271Y-11229D01* +X50016Y-15450D01* +X-91652D01* +G03X-92685Y-83669I-8347J-33991D01* +G02X-85838Y-91705I1260J-5861D01* +G03X-87910Y-108869I32636J-12647D01* +G02X-94769Y-115471I-5948J-685D01* +G03X-132904Y-162016I-5233J-34608D01* +G02X-137051Y-169873I-5617J-2058D01* +G02X-141806Y-169269I-1670J5871D01* +G03X-187884Y-200273I-11147J-33176D01* +G03X-187951Y-202440I34941J-2167D01* +G01X-236876D01* +G03X-302943Y-182801I-34780J3944D01* +G02X-306338Y-184145I-2567J1524D01* +G03X-337228Y-246682I-12710J-32620D01* +G02X-335536Y-255399I-3098J-5124D01* +G03X-340312Y-264171I28076J-20973D01* +G02X-343742Y-265931I-2773J1182D01* +G03X-380522Y-280471I-7773J-34128D01* +G02X-389696Y-281062I-4835J3557D01* +G02X-391346Y-278254I9849J7676D01* +G03X-457800Y-290742I-31554J-15144D01* +G03X-457899Y-293372I34912J-2630D01* +G01X-792626D01* +G37* +G36* +X-620995Y-366030D02* +X-532254D01* +X-531241Y-374387D01* +X-528263Y-382261D01* +X-523491Y-389196D01* +X-517201Y-394791D01* +X-509757Y-398722D01* +X-501590Y-400762D01* +X-497370Y-401032D01* +X-489016Y-399991D01* +X-481153Y-396986D01* +X-474234Y-392191D01* +X-470355Y-387800D01* +X-448234D01* +X-447221Y-396157D01* +X-444243Y-404031D01* +X-439471Y-410966D01* +X-433181Y-416561D01* +X-425737Y-420492D01* +X-417570Y-422532D01* +X-413350Y-422802D01* +X-404996Y-421761D01* +X-397133Y-418756D01* +X-390214Y-413961D01* +X-384640Y-407652D01* +X-380734Y-400195D01* +X-378721Y-392021D01* +X-378466Y-387800D01* +X378138D01* +X381669Y-390940D01* +X389113Y-394872D01* +X397280Y-396912D01* +X401500Y-397182D01* +X409380Y-396200D01* +X481666D01* +X482678Y-404557D01* +X485657Y-412431D01* +X490429Y-419366D01* +X496719Y-424960D01* +X504163Y-428892D01* +X512330Y-430932D01* +X516550Y-431202D01* +X524904Y-430161D01* +X532767Y-427156D01* +X533145Y-426894D01* +X561648D01* +G03X588999Y-461048I35000J0D01* +G01X-464047D01* +G03X-525992Y-483418I-35012J0D01* +G01X-529511Y-488391D01* +X-532118Y-493907D01* +X-533728Y-499792D01* +X-534142Y-502818D01* +G03X-534292Y-506058I34862J-3240D01* +G01X-543860D01* +X-544899Y-455599D01* +X-535303Y-423994D01* +X-535304Y-423989D01* +X-541249Y-406017D01* +X-541257Y-406009D01* +X-541266Y-406004D01* +X-541272Y-406002D01* +X-541278Y-406001D01* +X-619394Y-409996D01* +X-619399Y-409989D01* +X-619401Y-409984D01* +X-620995Y-366030D01* +G37* +G36* +X-543860Y-506058D02* +X-534292D01* +G03X-464966Y-499100I35013J0D01* +G01X-332834D01* +X-331821Y-507457D01* +X-328843Y-515331D01* +X-324071Y-522266D01* +X-317781Y-527861D01* +X-310337Y-531792D01* +X-302169Y-533832D01* +X-297950Y-534102D01* +X-289596Y-533061D01* +X-281733Y-530056D01* +X-274814Y-525261D01* +X-269240Y-518952D01* +X-265334Y-511495D01* +X-263488Y-504000D01* +X-252284D01* +X-251271Y-512357D01* +X-248293Y-520231D01* +X-243521Y-527166D01* +X-237231Y-532761D01* +X-229787Y-536692D01* +X-221619Y-538732D01* +X-217400Y-539002D01* +X-209046Y-537961D01* +X-201183Y-534956D01* +X-194264Y-530161D01* +X-188690Y-523852D01* +X-184784Y-516395D01* +X-182771Y-508221D01* +X-182516Y-504000D01* +X80350D01* +X80848Y-508117D01* +X83827Y-515991D01* +X88599Y-522926D01* +X94889Y-528520D01* +X102333Y-532452D01* +X110500Y-534492D01* +X114720Y-534762D01* +X123074Y-533721D01* +X130937Y-530716D01* +X137856Y-525921D01* +X143430Y-519612D01* +X145856Y-514980D01* +X450816D01* +X451828Y-523337D01* +X454807Y-531211D01* +X459579Y-538146D01* +X465869Y-543740D01* +X473313Y-547672D01* +X481480Y-549712D01* +X485700Y-549982D01* +X494054Y-548941D01* +X501917Y-545936D01* +X508836Y-541140D01* +X514410Y-534832D01* +X518316Y-527374D01* +X520328Y-519200D01* +X520584Y-514980D01* +X645159D01* +G03X695764Y-514783I25209J24293D01* +G02X699816Y-514846I1992J-2221D01* +G03X758853Y-489393I24031J25454D01* +G01X822449D01* +X822449Y-586049D01* +X756953D01* +G03X689354Y-573295I-35003J0D01* +G02X678643Y-574298I-5608J2190D01* +G03X616514Y-592268I-27339J-21866D01* +G03X616300Y-596137I34790J-3869D01* +G01X566455D01* +X564443Y-590819D01* +X559671Y-583884D01* +X553381Y-578289D01* +X545937Y-574358D01* +X537770Y-572317D01* +X533550Y-572048D01* +X525196Y-573089D01* +X517333Y-576094D01* +X510414Y-580889D01* +X504840Y-587198D01* +X500934Y-594655D01* +X500049Y-598248D01* +X491981D01* +G03X430465Y-575396I-35003J0D01* +G02X421620Y-575462I-4453J4009D01* +G03X373063Y-572833I-25641J-23845D01* +G03X316077Y-597499I-22075J-27160D01* +G03X315987Y-600009I34916J-2511D01* +G01X253962D01* +X251443Y-593349D01* +X246671Y-586414D01* +X240381Y-580819D01* +X232937Y-576888D01* +X224770Y-574847D01* +X220550Y-574578D01* +X212196Y-575618D01* +X204333Y-578623D01* +X197414Y-583419D01* +X191840Y-589728D01* +X187934Y-597185D01* +X186711Y-602150D01* +X170364D01* +X169351Y-593793D01* +X166373Y-585919D01* +X161601Y-578984D01* +X155311Y-573389D01* +X147867Y-569458D01* +X139700Y-567417D01* +X135480Y-567148D01* +X127126Y-568188D01* +X119263Y-571193D01* +X112344Y-575989D01* +X106770Y-582298D01* +X102864Y-589755D01* +X100851Y-597929D01* +X100596Y-602150D01* +X53903D01* +X53401Y-598013D01* +X50423Y-590139D01* +X45651Y-583204D01* +X39361Y-577609D01* +X31917Y-573678D01* +X23750Y-571637D01* +X19530Y-571368D01* +X11176Y-572408D01* +X3313Y-575413D01* +X-3606Y-580209D01* +X-9180Y-586518D01* +X-13086Y-593975D01* +X-15098Y-602149D01* +X-15132Y-602710D01* +X-31386D01* +X-32398Y-594353D01* +X-35377Y-586479D01* +X-40149Y-579544D01* +X-46439Y-573949D01* +X-53883Y-570018D01* +X-62050Y-567978D01* +X-66270Y-567708D01* +X-74624Y-568749D01* +X-82487Y-571754D01* +X-89406Y-576549D01* +X-94979Y-582858D01* +X-98885Y-590315D01* +X-100667Y-597550D01* +X-149916D01* +X-150928Y-589193D01* +X-153907Y-581319D01* +X-158679Y-574384D01* +X-164969Y-568789D01* +X-172413Y-564858D01* +X-180580Y-562818D01* +X-184800Y-562548D01* +X-193154Y-563589D01* +X-201017Y-566594D01* +X-207936Y-571389D01* +X-213509Y-577698D01* +X-217415Y-585155D01* +X-219428Y-593329D01* +X-219684Y-597550D01* +X-248195D01* +X-249128Y-589843D01* +X-252107Y-581969D01* +X-256879Y-575034D01* +X-263169Y-569439D01* +X-270613Y-565508D01* +X-278780Y-563468D01* +X-283000Y-563198D01* +X-291354Y-564239D01* +X-299217Y-567244D01* +X-306136Y-572039D01* +X-311709Y-578348D01* +X-315615Y-585805D01* +X-317628Y-593979D01* +X-317883Y-598190D01* +X-328076D01* +X-329088Y-589833D01* +X-332067Y-581959D01* +X-336839Y-575024D01* +X-343129Y-569429D01* +X-350573Y-565498D01* +X-358740Y-563458D01* +X-362960Y-563188D01* +X-371314Y-564229D01* +X-379177Y-567234D01* +X-386096Y-572029D01* +X-391669Y-578338D01* +X-395575Y-585795D01* +X-397588Y-593969D01* +X-397844Y-598190D01* +X-488883D01* +G03X-535293Y-565655I-35006J-566D01* +G02X-543243Y-559858I-1945J5682D01* +G01X-543000Y-547799D01* +X-543860Y-506058D01* +G37* +G36* +X-541750Y-823634D02* +X-541332Y-692300D01* +X-504334D01* +X-503321Y-700657D01* +X-500343Y-708531D01* +X-495571Y-715466D01* +X-489281Y-721061D01* +X-481837Y-724992D01* +X-473669Y-727032D01* +X-469450Y-727302D01* +X-461096Y-726261D01* +X-453233Y-723256D01* +X-446314Y-718461D01* +X-440740Y-712152D01* +X-436834Y-704695D01* +X-435136Y-697800D01* +X-396884D01* +X-395871Y-706157D01* +X-392893Y-714031D01* +X-388121Y-720966D01* +X-381831Y-726561D01* +X-374387Y-730492D01* +X-366219Y-732532D01* +X-362000Y-732802D01* +X-353646Y-731761D01* +X-345783Y-728756D01* +X-338864Y-723961D01* +X-333290Y-717652D01* +X-329384Y-710195D01* +X-327371Y-702021D01* +X-327119Y-697855D01* +X-282503D01* +G03X-215973Y-713109I35014J0D01* +G02X-205856Y-712891I5128J-3119D01* +G03X-142607Y-701170I29103J19465D01* +G01X-95644D01* +X-94631Y-709527D01* +X-91653Y-717401D01* +X-86881Y-724336D01* +X-80591Y-729931D01* +X-73147Y-733862D01* +X-64979Y-735902D01* +X-60760Y-736172D01* +X-52406Y-735131D01* +X-44543Y-732126D01* +X-37624Y-727331D01* +X-32050Y-721022D01* +X-28144Y-713565D01* +X-26192Y-705640D01* +X-7974D01* +X-6961Y-713997D01* +X-3983Y-721871D01* +X789Y-728806D01* +X7079Y-734400D01* +X14523Y-738332D01* +X22690Y-740372D01* +X26910Y-740642D01* +X35264Y-739601D01* +X43127Y-736596D01* +X50046Y-731801D01* +X55620Y-725492D01* +X59526Y-718035D01* +X61538Y-709860D01* +X61794Y-705640D01* +X107329D01* +G03X172955Y-714760I34367J6625D01* +G02X182356Y-713250I5281J-2861D01* +G03X238168Y-709548I26511J22882D01* +G02X248651Y-710835I4888J-3526D01* +G03X309528Y-710143I30242J17646D01* +G02X319890Y-710918I4958J-3370D01* +G03X386318Y-698400I31529J15198D01* +G01X415116D01* +X416128Y-706757D01* +X419107Y-714631D01* +X423879Y-721566D01* +X430169Y-727160D01* +X437613Y-731092D01* +X445780Y-733132D01* +X450000Y-733402D01* +X458354Y-732361D01* +X466217Y-729356D01* +X473136Y-724560D01* +X478710Y-718252D01* +X482616Y-710794D01* +X484628Y-702620D01* +X484884Y-698400D01* +X585084D01* +X588329Y-703116D01* +X594619Y-708710D01* +X602063Y-712642D01* +X610230Y-714682D01* +X614450Y-714952D01* +X622804Y-713911D01* +X630667Y-710906D01* +X637586Y-706110D01* +X643160Y-699802D01* +X647066Y-692344D01* +X648911Y-684850D01* +X683316D01* +X684328Y-693207D01* +X687307Y-701081D01* +X692079Y-708016D01* +X698369Y-713610D01* +X705813Y-717542D01* +X713980Y-719582D01* +X718200Y-719852D01* +X726554Y-718811D01* +X734417Y-715806D01* +X741336Y-711010D01* +X746910Y-704702D01* +X750816Y-697244D01* +X752828Y-689070D01* +X753084Y-684850D01* +X822449D01* +X822448Y-822490D01* +X822443Y-822496D01* +X822439Y-822499D01* +X822434Y-822500D01* +X740055D01* +G02X736815Y-811451I0J5999D01* +G03X698986Y-811451I-18915J29450D01* +G02X695742Y-822500I-3244J-5048D01* +G01X640368D01* +G02X636921Y-811591I0J5999D01* +G03X584671Y-769062I-20123J28638D01* +G02X574896Y-770896I-5507J2382D01* +G03X519938Y-813428I-24896J-24604D01* +G02X514784Y-822500I-5154J-3072D01* +G01X482913D01* +G02X477573Y-813770I0J5998D01* +G03X415228Y-813771I-31173J15917D01* +G02X409884Y-822500I-5344J-2729D01* +G01X364596D01* +G02X359541Y-813272I0J5999D01* +G03X300783Y-813729I-29527J18819D01* +G02X295461Y-822500I-5322J-2771D01* +G01X287141D01* +G02X281906Y-813573I0J5999D01* +G03X220794Y-813573I-30556J17074D01* +G02X215556Y-822500I-5238J-2927D01* +G01X182062D01* +G02X176641Y-813933I0J5999D01* +G03X113731Y-813874I-31441J15394D01* +G02X108336Y-822500I-5395J-2626D01* +G01X68064D01* +G02X63152Y-813057I0J5999D01* +G03X6310Y-813004I-28402J20456D01* +G02X1433Y-822500I-4877J-3495D01* +G01X-31738Y-822476D01* +G02X-36229Y-813208I508J5968D01* +G03X-94750Y-813209I-29261J19207D01* +G02X-99768Y-822500I-5018J-3290D01* +G01X-146118D01* +G02X-150533Y-812438I-14J5993D01* +G03X-207321Y-772540I-25752J23710D01* +G03X-201728Y-812842I31038J-16232D01* +G02X-206485Y-822500I-4757J-3657D01* +G01X-243902Y-822476D01* +G02X-247972Y-812642I508J5970D01* +G03X-300363Y-812531I-26146J23272D01* +G02X-304863Y-822500I-4500J-3969D01* +G01X-328202D01* +G02X-333900Y-814625I-13J5989D01* +G03X-400350Y-814777I-33250J10927D01* +G02X-405999Y-822677I-5689J-1902D01* +G01X-438477Y-822910D01* +G02X-443185Y-813139I-42J6000D01* +G03X-497317Y-813527I-27225J22007D01* +G02X-501888Y-823364I-4571J-3857D01* +G01X-541740Y-823648D01* +X-541749Y-823640D01* +X-541750Y-823634D01* +G37* +G36* +X-541639Y-631272D02* +X-537894Y-630844D01* +G03X-488883Y-598190I14005J32087D01* +G01X-397844D01* +X-396831Y-606547D01* +X-393853Y-614421D01* +X-389081Y-621356D01* +X-382791Y-626951D01* +X-375347Y-630882D01* +X-367179Y-632922D01* +X-362960Y-633192D01* +X-354606Y-632151D01* +X-346743Y-629146D01* +X-339824Y-624351D01* +X-334250Y-618042D01* +X-330344Y-610585D01* +X-328331Y-602411D01* +X-328077Y-598200D01* +X-317884D01* +X-316871Y-606557D01* +X-313893Y-614431D01* +X-309121Y-621366D01* +X-302831Y-626961D01* +X-295387Y-630892D01* +X-287219Y-632932D01* +X-283000Y-633202D01* +X-274646Y-632161D01* +X-266783Y-629156D01* +X-259864Y-624361D01* +X-254290Y-618052D01* +X-250384Y-610595D01* +X-248371Y-602421D01* +X-248116Y-598200D01* +X-219605D01* +X-218671Y-605907D01* +X-215693Y-613781D01* +X-210921Y-620716D01* +X-204631Y-626311D01* +X-197187Y-630242D01* +X-189019Y-632282D01* +X-184800Y-632552D01* +X-176446Y-631511D01* +X-168583Y-628506D01* +X-161664Y-623711D01* +X-156090Y-617402D01* +X-152184Y-609945D01* +X-150402Y-602710D01* +X-101154D01* +X-100141Y-611067D01* +X-97163Y-618941D01* +X-92391Y-625876D01* +X-86101Y-631471D01* +X-78657Y-635402D01* +X-70489Y-637442D01* +X-66270Y-637712D01* +X-57916Y-636671D01* +X-50053Y-633666D01* +X-43134Y-628871D01* +X-37560Y-622562D01* +X-33654Y-615105D01* +X-31641Y-606931D01* +X-31607Y-606370D01* +X-15354D01* +X-14341Y-614727D01* +X-11363Y-622601D01* +X-6591Y-629536D01* +X-301Y-635130D01* +X7143Y-639062D01* +X15310Y-641102D01* +X19530Y-641372D01* +X27884Y-640331D01* +X35747Y-637326D01* +X42666Y-632531D01* +X48240Y-626222D01* +X52146Y-618765D01* +X54158Y-610590D01* +X54414Y-606370D01* +X101107D01* +X101608Y-610507D01* +X104587Y-618381D01* +X109359Y-625316D01* +X115649Y-630910D01* +X123093Y-634842D01* +X131260Y-636882D01* +X135480Y-637152D01* +X143834Y-636111D01* +X151697Y-633106D01* +X158616Y-628311D01* +X164190Y-622002D01* +X168096Y-614545D01* +X169318Y-609580D01* +X185666D01* +X186678Y-617937D01* +X189657Y-625811D01* +X194429Y-632746D01* +X200719Y-638340D01* +X208163Y-642272D01* +X216330Y-644312D01* +X220550Y-644582D01* +X228904Y-643541D01* +X236767Y-640536D01* +X243686Y-635741D01* +X249260Y-629432D01* +X253166Y-621975D01* +X255178Y-613801D01* +X255434Y-609580D01* +X317321D01* +G03X373915Y-626466I33672J9570D01* +G03X422505Y-622153I22074J27172D01* +G02X431822Y-622586I4481J-4030D01* +G03X490856Y-607050I25157J24338D01* +G01X498666D01* +X499678Y-615407D01* +X502657Y-623281D01* +X507429Y-630216D01* +X513719Y-635810D01* +X521163Y-639742D01* +X529330Y-641782D01* +X533550Y-642052D01* +X541904Y-641011D01* +X549767Y-638006D01* +X556686Y-633210D01* +X562260Y-626902D01* +X566166Y-619444D01* +X568178Y-611270D01* +X568434Y-607050D01* +X618044D01* +G03X683935Y-608808I33260J10913D01* +G02X694607Y-607902I5566J-2252D01* +G03X756953Y-586049I27343J21853D01* +G01X822449D01* +X822449Y-684850D01* +X753084D01* +X752071Y-676493D01* +X749093Y-668619D01* +X744321Y-661684D01* +X738031Y-656089D01* +X730587Y-652158D01* +X722420Y-650117D01* +X718200Y-649848D01* +X709846Y-650889D01* +X701983Y-653894D01* +X695064Y-658689D01* +X689490Y-664998D01* +X685584Y-672455D01* +X683738Y-679950D01* +X649334D01* +X648321Y-671593D01* +X645343Y-663719D01* +X640571Y-656784D01* +X634281Y-651189D01* +X626837Y-647258D01* +X618670Y-645217D01* +X614450Y-644948D01* +X606096Y-645989D01* +X598233Y-648994D01* +X591314Y-653789D01* +X585740Y-660098D01* +X581834Y-667555D01* +X579821Y-675729D01* +X579566Y-679950D01* +X479366D01* +X476121Y-675234D01* +X469831Y-669639D01* +X462387Y-665708D01* +X454220Y-663667D01* +X450000Y-663398D01* +X441646Y-664439D01* +X433783Y-667444D01* +X426864Y-672239D01* +X421290Y-678548D01* +X417384Y-686005D01* +X415371Y-694179D01* +X415278Y-695720D01* +X386420D01* +G03X321025Y-678362I-35001J0D01* +G02X310238Y-677639I-5218J2983D01* +G03X249592Y-674012I-31361J-15549D01* +G02X239491Y-673396I-4854J3529D01* +G03X177625Y-674610I-30612J-16951D01* +G02X167303Y-675133I-5319J2860D01* +G03X106958Y-694740I-25600J-23877D01* +G03X106696Y-699014I34738J-4275D01* +G01X60991D01* +X60781Y-697283D01* +X57803Y-689409D01* +X53031Y-682474D01* +X46741Y-676879D01* +X39297Y-672948D01* +X31130Y-670907D01* +X26910Y-670638D01* +X18556Y-671678D01* +X10693Y-674683D01* +X3774Y-679479D01* +X-1800Y-685788D01* +X-5706Y-693245D01* +X-7657Y-701170D01* +X-25876D01* +X-26888Y-692813D01* +X-29867Y-684939D01* +X-34639Y-678004D01* +X-40929Y-672409D01* +X-48373Y-668478D01* +X-56540Y-666438D01* +X-60760Y-666168D01* +X-69114Y-667209D01* +X-76977Y-670214D01* +X-83896Y-675009D01* +X-89469Y-681318D01* +X-93375Y-688775D01* +X-94521Y-693426D01* +X-141740D01* +G03X-208277Y-678191I-35013J0D01* +G02X-218394Y-678409I-5128J3120D01* +G03X-282269Y-693815I-29107J-19437D01* +G03X-282503Y-697800I34780J-4040D01* +G01X-327116D01* +X-328128Y-689443D01* +X-331107Y-681569D01* +X-335879Y-674634D01* +X-342169Y-669039D01* +X-349613Y-665108D01* +X-357780Y-663068D01* +X-362000Y-662798D01* +X-370354Y-663839D01* +X-378217Y-666844D01* +X-385136Y-671639D01* +X-390709Y-677948D01* +X-394615Y-685405D01* +X-396313Y-692300D01* +X-434566D01* +X-435578Y-683943D01* +X-438557Y-676069D01* +X-443329Y-669134D01* +X-449619Y-663539D01* +X-457063Y-659608D01* +X-465230Y-657568D01* +X-469450Y-657298D01* +X-477804Y-658339D01* +X-485667Y-661344D01* +X-492586Y-666139D01* +X-498159Y-672448D01* +X-502065Y-679905D01* +X-504078Y-688079D01* +X-504334Y-692300D01* +X-541332D01* +X-541151Y-635546D01* +X-541639Y-631272D01* +G37* +G36* +X-472349Y-483684D02* +G03X-464047Y-461048I-26710J22636D01* +G01X588999D01* +G03X613632Y-396290I7650J34154D01* +G02X611096Y-393300I3094J5195D01* +G01X696466D01* +X697478Y-401657D01* +X700457Y-409531D01* +X705229Y-416466D01* +X711519Y-422060D01* +X718963Y-425992D01* +X727130Y-428032D01* +X731350Y-428302D01* +X739704Y-427261D01* +X747567Y-424256D01* +X754486Y-419460D01* +X760060Y-413152D01* +X763966Y-405694D01* +X765978Y-397520D01* +X766234Y-393300D01* +X822450D01* +X822449Y-489393D01* +X758853D01* +G03X698445Y-465307I-35006J0D01* +G02X694590Y-465414I-1991J2221D01* +G03X635438Y-488329I-24226J-25268D01* +G03X635359Y-490687I34929J-2358D01* +G01X510554D01* +X505531Y-486219D01* +X498087Y-482288D01* +X489920Y-480247D01* +X485700Y-479978D01* +X477346Y-481019D01* +X469483Y-484024D01* +X462564Y-488819D01* +X456990Y-495128D01* +X454564Y-499760D01* +X149604D01* +X148591Y-491403D01* +X145613Y-483529D01* +X140841Y-476594D01* +X134551Y-470999D01* +X127107Y-467068D01* +X118940Y-465027D01* +X114720Y-464758D01* +X106366Y-465798D01* +X98503Y-468803D01* +X91584Y-473599D01* +X86010Y-479908D01* +X82104Y-487365D01* +X80091Y-495539D01* +X79836Y-499760D01* +X-183029D01* +X-183528Y-495643D01* +X-186507Y-487769D01* +X-191279Y-480834D01* +X-197569Y-475239D01* +X-205013Y-471308D01* +X-213180Y-469268D01* +X-217400Y-468998D01* +X-225754Y-470039D01* +X-233617Y-473044D01* +X-240536Y-477839D01* +X-246109Y-484148D01* +X-250015Y-491605D01* +X-251861Y-499100D01* +X-263066D01* +X-264078Y-490743D01* +X-267057Y-482869D01* +X-271829Y-475934D01* +X-278119Y-470339D01* +X-285563Y-466408D01* +X-293730Y-464368D01* +X-297950Y-464098D01* +X-306304Y-465139D01* +X-314167Y-468144D01* +X-321086Y-472939D01* +X-326659Y-479248D01* +X-330565Y-486705D01* +X-332578Y-494879D01* +X-332834Y-499100D01* +X-464966D01* +G03X-472349Y-483684I-34314J-6959D01* +G37* +G36* +X-470355Y-387800D02* +G01X-468660Y-385882D01* +X-464754Y-378425D01* +X-462741Y-370250D01* +X-462486Y-366030D01* +X-440365D01* +X-442059Y-367948D01* +X-445965Y-375405D01* +X-447978Y-383579D01* +X-448234Y-387800D01* +X-470355D01* +G37* +G36* +X-435136Y-697800D02* +X-434821Y-696520D01* +X-434566Y-692300D01* +X-396313D01* +X-396628Y-693579D01* +X-396884Y-697800D01* +X-435136D01* +G37* +G36* +X-328607Y39190D02* +G02X-328607Y39237I5998J0D01* +G01X-328551Y47087D01* +G02X-319576Y52254I5998J-40D01* +G03X-269590Y69983I17357J30393D01* +G02X-265956Y71777I2798J-1091D01* +G03X-220388Y102449I10665J33341D01* +G01X-159683D01* +G03X-90485Y109934I35004J0D01* +G02X-89641Y112574I2989J499D01* +G02X-87186Y113787I6098J-9251D01* +G03X-66959Y156537I-13221J32415D01* +G02X-60901Y164300I5735J1770D01* +G03X-45825Y166800I1949J34954D01* +G02X-38216Y159723I1763J-5733D01* +G03X-35732Y136892I34143J-7836D01* +G02X-38604Y129312I-5572J-2223D01* +G03X10593Y87653I15769J-31257D01* +G01X41948D01* +G03X106970Y69646I35004J0D01* +G02X111264Y70481I2554J-1674D01* +G03X134975Y136277I13431J32330D01* +G02X133408Y140665I1131J2877D01* +G03X129546Y164544I-34382J6691D01* +G02X133722Y173100I5376J2674D01* +G03X161751Y207403I-6977J34304D01* +G01X199269D01* +G03X199956Y200251I35014J-245D01* +G02X194839Y193117I-5879J-1185D01* +G03X233614Y165308I4461J-34717D01* +G02X238731Y172443I5871J1192D01* +G03X239382Y241787I-4461J34717D01* +G02X234477Y249328I866J5929D01* +G03X235751Y259005I-33768J9368D01* +G02X242372Y265026I6004J48D01* +G03X273185Y277804I3611J34833D01* +G02X282938Y277197I4662J-3748D01* +G03X294754Y265620I29685J18480D01* +G02X294709Y255281I-3070J-5156D01* +G03X283773Y204840I17634J-30229D01* +G02X283158Y194917I-3867J-4741D01* +G03X268485Y151840I17843J-30115D01* +G02X263781Y143683I-5572J-2222D01* +G03X261015Y74936I5081J-34634D01* +G02X265467Y67537I-1337J-5844D01* +G03X270153Y39080I33797J-9049D01* +G02X268063Y30502I-4997J-3326D01* +G03X259393Y-24005I16949J-30639D01* +G01X246977D01* +G03X236088Y1372I-35014J0D01* +G02X235868Y9081I4462J3985D01* +G03X173514Y33406I-27448J21721D01* +G03X173415Y30778I34904J-2628D01* +G01X36454D01* +X36372Y31457D01* +X33393Y39331D01* +X28621Y46266D01* +X22331Y51861D01* +X14887Y55792D01* +X6720Y57832D01* +X2500Y58102D01* +X-5854Y57061D01* +X-13717Y54056D01* +X-20636Y49261D01* +X-26210Y42952D01* +X-30116Y35495D01* +X-32129Y27321D01* +X-32384Y23100D01* +X-205508D01* +G03X-266540Y24263I-30843J-16553D01* +G02X-276491Y23669I-5173J3011D01* +G03X-319935Y33821I-27874J-21250D01* +G02X-328607Y39190I-2674J5369D01* +G37* +G36* +X-328498Y806488D02* +G01X-328493Y806497D01* +X-328487Y806499D01* +X380901Y807197D01* +X478098Y715549D01* +X478099Y715544D01* +X478058Y712167D01* +X413015D01* +G03X346590Y727631I-35013J0D01* +G02X342087Y726526I-2737J1425D01* +G03X310178Y720630I-10319J-33445D01* +G02X301239Y722776I-3567J4833D01* +G03X235189Y711502I-31319J-15632D01* +G03X234920Y707171I34744J-4331D01* +G01X221102D01* +G03X161603Y724254I-34261J-7173D01* +G02X157767Y723843I-2161J2064D01* +G03X107739Y714828I-20746J-28194D01* +G02X97496Y715166I-5019J3286D01* +G03X38310Y717972I-30476J-17227D01* +G02X27985Y718798I-4921J3432D01* +G03X-30036Y726461I-31526J-15218D01* +G02X-33846Y725846I-2273J1974D01* +G03X-71361Y726410I-19202J-29305D01* +G02X-80020Y729172I-3138J5116D01* +G03X-142499Y733010I-32202J-13746D01* +G02X-146127Y731699I-2590J1491D01* +G03X-178963Y728518I-13439J-32344D01* +G02X-187645Y730815I-3324J4994D01* +G03X-247567Y735144I-31255J-15751D01* +G02X-251294Y734148I-2454J1710D01* +G03X-285587Y733042I-16161J-31110D01* +G02X-293440Y734503I-3107J5134D01* +G03X-322111Y748068I-27691J-21445D01* +G02X-328281Y754040I-155J6013D01* +G01X-328498Y806488D01* +G37* +G36* +X-327938Y672078D02* +G02X-321817Y678085I6009J0D01* +G03X-302992Y683139I697J34990D01* +G02X-295140Y681677I3104J-5146D01* +G03X-238793Y683017I27680J21414D01* +G02X-235066Y684012I2449J-1695D01* +G03X-199507Y685922I16164J31027D01* +G02X-190825Y683625I3323J-4996D01* +G03X-129291Y681820I31255J15751D01* +G02X-125662Y683130I2597J-1513D01* +G03X-93909Y685620I13441J32310D01* +G02X-85250Y682858I3139J-5114D01* +G03X-26553Y673710I32200J13724D01* +G02X-22744Y674324I2270J-1961D01* +G03X25170Y683568I19208J29236D01* +G02X35495Y682742I4921J-3437D01* +G03X96301Y678773I31525J15208D01* +G02X106544Y678434I5019J-3269D01* +G03X162257Y671397I30479J17242D01* +G02X166092Y671807I2163J-2090D01* +G03X221102Y707171I20749J28191D01* +G01X234920D01* +G03X291512Y679599I35013J0D01* +G02X300451Y677454I3569J-4826D01* +G03X363170Y677608I31321J15624D01* +G02X366763Y679007I2629J-1439D01* +G03X413015Y712167I11239J33160D01* +G01X478058D01* +X477699Y682156D01* +X477694Y682147D01* +X453104Y662697D01* +X453101Y662690D01* +X453100Y662686D01* +Y623793D01* +G02X442855Y619555I-6000J2D01* +G03X380530Y597137I-27313J-21911D01* +G01X373549D01* +G03X313750Y621852I-35007J0D01* +G02X304390Y623585I-4016J4453D01* +G03X246490Y630304I-31182J-15877D01* +G02X242443Y630120I-2124J2131D01* +G03X185166Y606687I-22455J-26832D01* +G03X184998Y603256I34838J-3431D01* +G01X171739D01* +G03X104929Y615618I-34946J-2146D01* +G02X94837Y614871I-5284J2843D01* +G03X54337Y626645I-28046J-20929D01* +G02X51603Y627088I-938J2869D01* +G02X50065Y629289I7274J6721D01* +G03X-14951Y614109I-30118J-17829D01* +G03X-15050Y611480I34926J-2629D01* +G01X-38020D01* +G03X-100527Y614591I-32033J-14106D01* +G02X-111108Y615225I-5118J3198D01* +G03X-151688Y628553I-28944J-19686D01* +G02X-154411Y629063I-867J2895D01* +G02X-155893Y631298I8561J7286D01* +G03X-221264Y617733I-30548J-17083D01* +G03X-221441Y614212I34827J-3522D01* +G01X-327696D01* +X-327938Y672063D01* +G02X-327938Y672078I6009J7D01* +G37* +G36* +X-327696Y614212D02* +G01X-221441D01* +G03X-174802Y581197I35005J0D01* +G02X-171254Y579685I871J-2876D01* +G03X-170578Y578420I31208J15861D01* +G01X-250196D01* +X-251208Y586777D01* +X-254187Y594651D01* +X-258959Y601586D01* +X-265249Y607180D01* +X-272693Y611112D01* +X-280860Y613152D01* +X-285080Y613422D01* +X-293434Y612381D01* +X-301297Y609376D01* +X-308216Y604581D01* +X-313790Y598272D01* +X-317696Y590815D01* +X-319708Y582640D01* +X-319964Y578420D01* +X-327546D01* +X-327696Y614212D01* +G37* +G36* +X-327645Y174105D02* +G02X-327645Y174155I5997J0D01* +G01X-327246Y229505D01* +X-321357Y237529D01* +X-236572D01* +G03X-222407Y209406I34999J0D01* +G02X-221654Y205397I-1772J-2408D01* +G03X-173063Y212174I27746J-21348D01* +G02X-173668Y216396I1770J2408D01* +G03X-177542Y263008I-27909J21147D01* +G02X-173771Y272961I4478J3994D01* +G03X-142913Y307717I-4144J34756D01* +G01X-121570D01* +G03X-116714Y303779I24392J25113D01* +G02X-115982Y294962I-3665J-4743D01* +G02X-118507Y293238I-7371J8084D01* +G03X-130550Y242902I16907J-30654D01* +G02X-130694Y239682I-2630J-1496D01* +G02X-132495Y238170I-8182J7917D01* +G03X-127274Y179067I21132J-27916D01* +G02X-125775Y170347I-3262J-5050D01* +G03X-134595Y138716I25368J-24119D01* +G02X-135439Y136076I-2966J-506D01* +G02X-137875Y134870I-6760J10591D01* +G03X-159639Y104193I13198J-32422D01* +G03X-159683Y102449I34960J-1744D01* +G01X-220388D01* +G03X-258315Y139992I-34903J2669D01* +G02X-264741Y144937I-509J5986D01* +G03X-318382Y169075I-34610J-5242D01* +G02X-321648Y168108I-3266J5030D01* +G02X-327645Y174105I-0J5997D01* +G37* +G36* +X-327546Y578420D02* +G01X-319964D01* +X-318951Y570063D01* +X-315973Y562189D01* +X-311201Y555254D01* +X-304911Y549659D01* +X-297467Y545728D01* +X-289300Y543687D01* +X-285080Y543418D01* +X-276726Y544458D01* +X-268863Y547463D01* +X-261944Y552259D01* +X-256370Y558568D01* +X-252464Y566025D01* +X-250451Y574199D01* +X-250196Y578420D01* +X-170578D01* +G03X-109572Y578319I30532J17126D01* +G02X-100465Y579571I5080J-3204D01* +G02X-98672Y577224I-13561J-12218D01* +G03X-35052Y597374I28619J20150D01* +G01X-12084D01* +G03X32402Y578734I32059J14106D01* +G02X36463Y576454I1035J-2913D01* +G03X98651Y579412I30333J17475D01* +G02X108743Y580158I5286J-2874D01* +G03X171805Y601110I28050J20952D01* +G01X185063D01* +G03X246720Y580636I34941J2146D01* +G02X250767Y580820I2124J-2118D01* +G03X297999Y582958I22449J26857D01* +G02X307360Y581226I4019J-4443D01* +G03X373549Y597137I31182J15911D01* +G01X380530D01* +G03X442483Y575276I35012J506D01* +G02X453100Y571443I4610J-3852D01* +G01X453099Y550755D01* +X453095Y550746D01* +X407650Y507648D01* +X403452Y499999D01* +X285008D01* +G03X221625Y520493I-35005J0D01* +G02X211085Y522007I-4874J3516D01* +G03X144330Y511239I-31935J-14327D01* +G03X144148Y507675I34818J-3564D01* +G01X83264D01* +X83181Y508357D01* +X80203Y516231D01* +X75431Y523166D01* +X69141Y528761D01* +X61697Y532692D01* +X53529Y534732D01* +X49310Y535002D01* +X40956Y533961D01* +X33093Y530956D01* +X26174Y526161D01* +X20600Y519852D01* +X16694Y512395D01* +X14725Y504400D01* +X6484D01* +X5471Y512757D01* +X2493Y520631D01* +X-2279Y527566D01* +X-8569Y533160D01* +X-16013Y537092D01* +X-24180Y539132D01* +X-28400Y539402D01* +X-36754Y538361D01* +X-44617Y535356D01* +X-51536Y530561D01* +X-57110Y524252D01* +X-61016Y516795D01* +X-62236Y511840D01* +X-147436D01* +X-148448Y520197D01* +X-151427Y528071D01* +X-156199Y535006D01* +X-162489Y540600D01* +X-169933Y544532D01* +X-178100Y546572D01* +X-182320Y546842D01* +X-190674Y545801D01* +X-198537Y542796D01* +X-205456Y538000D01* +X-211030Y531692D01* +X-214936Y524234D01* +X-216948Y516060D01* +X-217204Y511840D01* +X-226893D01* +X-228857Y517031D01* +X-233629Y523966D01* +X-239919Y529560D01* +X-247363Y533492D01* +X-255530Y535532D01* +X-259750Y535802D01* +X-268104Y534761D01* +X-275967Y531756D01* +X-282886Y526961D01* +X-288460Y520652D01* +X-292366Y513195D01* +X-294378Y505020D01* +X-294634Y500800D01* +X-327221D01* +X-327546Y578420D01* +G37* +G36* +X-327221Y500800D02* +X-294634D01* +X-293621Y492443D01* +X-290643Y484569D01* +X-285871Y477634D01* +X-279581Y472039D01* +X-272137Y468108D01* +X-263970Y466067D01* +X-259750Y465798D01* +X-251396Y466838D01* +X-243533Y469843D01* +X-236614Y474639D01* +X-231040Y480948D01* +X-227134Y488405D01* +X-225121Y496579D01* +X-224866Y500800D01* +X-215176D01* +X-213213Y495609D01* +X-208441Y488674D01* +X-202151Y483079D01* +X-194707Y479148D01* +X-186540Y477107D01* +X-182320Y476838D01* +X-173966Y477878D01* +X-166103Y480883D01* +X-159184Y485679D01* +X-153610Y491988D01* +X-149704Y499445D01* +X-148484Y504400D01* +X-63284D01* +X-62271Y496043D01* +X-59293Y488169D01* +X-54521Y481234D01* +X-48231Y475639D01* +X-40787Y471708D01* +X-32620Y469667D01* +X-28400Y469398D01* +X-20046Y470438D01* +X-12183Y473443D01* +X-5264Y478239D01* +X310Y484548D01* +X4216Y492005D01* +X6184Y500000D01* +X14426D01* +X15438Y491643D01* +X18417Y483769D01* +X23189Y476834D01* +X29479Y471239D01* +X36923Y467308D01* +X45090Y465268D01* +X49310Y464998D01* +X57664Y466039D01* +X65527Y469044D01* +X72446Y473839D01* +X78019Y480148D01* +X81926Y487605D01* +X83938Y495779D01* +X84194Y500000D01* +X145000D01* +G03X207568Y487246I34149J7675D01* +G02X218065Y485672I4832J-3566D01* +G03X285008Y499999I31938J14327D01* +G01X403452D01* +X398047Y490151D01* +X367198Y473095D01* +X340150Y433849D01* +X337331Y427970D01* +X337326Y427968D01* +G03X287546Y408074I-16496J-30950D01* +G03X307025Y364666I33253J-11152D01* +G01X302902Y356050D01* +Y356043D01* +X307263Y330406D01* +G03X285455Y317737I5544J-34648D01* +G02X275702Y318343I-4660J3778D01* +G03X210989Y299526I-29714J-18495D01* +G02X210974Y299056I-6003J-51D01* +G01X158961D01* +G03X93444Y316221I-35007J0D01* +G02X83058Y316537I-5102J3147D01* +G03X38125Y332016I-30839J-16564D01* +G02X30241Y338359I-1905J5704D01* +G03X-39527Y340889I-34790J3860D01* +G02X-45807Y334650I-6026J-215D01* +G03X-55219Y332957I1442J-35023D01* +G02X-62756Y339217I-1455J5915D01* +G03X-121570Y307717I-34421J-6387D01* +G01X-142913D01* +G03X-201918Y282241I-35003J0D01* +G02X-203239Y273144I-4488J-3993D01* +G02X-206724Y272150I-4542J9318D01* +G03X-236345Y241511I5170J-34636D01* +G03X-236572Y237529I34771J-3982D01* +G01X-321357D01* +X-300351Y266150D01* +X-290275Y289508D01* +G03X-317419Y349216I-24717J24787D01* +G01X-326592Y352349D01* +X-326599Y352358D01* +X-326600Y352362D01* +X-327221Y500800D01* +G37* +G36* +X-327119Y-697855D02* +X-327116Y-697800D01* +X-282503D01* +G03X-282503Y-697855I35014J-55D01* +G01X-327119D01* +G37* +G36* +X-292194Y-241299D02* +G02X-291004Y-237711I6006J0D01* +G01X-287757Y-232469D01* +G02X-284115Y-231207I2566J-1518D01* +G03X-236876Y-202440I12459J32711D01* +G01X-187951D01* +G03X-134618Y-232269I35008J0D01* +G02X-130823Y-232960I1486J-2608D01* +G03X-73128Y-233196I28929J19735D01* +G02X-69357Y-232397I2362J-1848D01* +G03X-43203Y-235149I16474J30904D01* +G02X-36450Y-238874I1154J-5892D01* +G03X22570Y-203224I32654J12620D01* +G02X23333Y-195155I4788J3618D01* +G03X34862Y-169188I-23477J25967D01* +G01X52049D01* +G03X98604Y-219601I28362J-20511D01* +G02X102689Y-220548I1557J-2565D01* +G03X133933Y-166722I29480J18869D01* +G02X129073Y-157671I304J5993D01* +G03X133948Y-138835I-30111J17842D01* +G02X139777Y-132668I5999J168D01* +G03X166567Y-122935I2468J34943D01* +G02X175346Y-123424I4162J-4328D01* +G03X228599Y-124145I26934J22357D01* +G02X237726Y-124266I4512J-3978D01* +G03X281190Y-132747I26923J22360D01* +G02X289159Y-134929I2833J-5298D01* +G03X351994Y-128762I29941J18125D01* +G02X360170Y-125376I5629J-2029D01* +G03X368881Y-128969I17582J30269D01* +G02X372991Y-136805I-1532J-5800D01* +G03X369882Y-156541I31594J-15090D01* +G02X367558Y-159863I-2977J-392D01* +G03X339456Y-193440I6912J-34333D01* +G02X329910Y-198150I-5988J107D01* +G03X299058Y-190060I-23329J-26092D01* +G02X295566Y-188064I-639J2936D01* +G03X245390Y-168324I-33264J-10912D01* +G02X241847Y-167434I-1191J2754D01* +G03X229320Y-217036I-29450J-18945D01* +G02X232863Y-217926I1191J-2755D01* +G03X270062Y-233125I29452J18962D01* +G02X273294Y-235166I376J-2984D01* +G03X341578Y-224466I33269J10919D01* +G02X351480Y-220591I5965J-653D01* +G03X398528Y-219585I22970J26420D01* +G02X407308Y-220151I4128J-4342D01* +G03X450317Y-166850I27144J22100D01* +G01X663566D01* +X664578Y-175207D01* +X667557Y-183081D01* +X672329Y-190016D01* +X678619Y-195610D01* +X686063Y-199542D01* +X694230Y-201582D01* +X698450Y-201852D01* +X706804Y-200811D01* +X714667Y-197806D01* +X721586Y-193010D01* +X727160Y-186702D01* +X731066Y-179244D01* +X733078Y-171070D01* +X733334Y-166850D01* +X767667D01* +G03X813490Y-177045I28551J20250D01* +G02X822450Y-182265I2960J-5219D01* +G01Y-238465D01* +G02X812852Y-243264I-5992J-14D01* +G03X757157Y-275740I-20980J-28016D01* +G01X722574D01* +X721562Y-267383D01* +X718583Y-259509D01* +X713811Y-252574D01* +X707521Y-246979D01* +X700077Y-243048D01* +X691910Y-241007D01* +X687690Y-240738D01* +X679336Y-241779D01* +X671473Y-244784D01* +X664554Y-249579D01* +X658980Y-255888D01* +X655074Y-263345D01* +X653061Y-271519D01* +X652806Y-275740D01* +X367347D01* +X361511Y-270549D01* +X354067Y-266618D01* +X345900Y-264577D01* +X341680Y-264308D01* +X333326Y-265348D01* +X325463Y-268353D01* +X318544Y-273149D01* +X312970Y-279458D01* +X309064Y-286915D01* +X307051Y-295089D01* +X306796Y-299310D01* +X246876D01* +X246263Y-297689D01* +X241491Y-290754D01* +X235201Y-285159D01* +X227757Y-281228D01* +X219590Y-279187D01* +X215370Y-278918D01* +X207016Y-279958D01* +X199153Y-282963D01* +X192234Y-287759D01* +X191906Y-288130D01* +X117754D01* +X116742Y-279773D01* +X113763Y-271899D01* +X108991Y-264964D01* +X102701Y-259369D01* +X95257Y-255438D01* +X87090Y-253397D01* +X82870Y-253128D01* +X74516Y-254168D01* +X66653Y-257173D01* +X59734Y-261969D01* +X54160Y-268278D01* +X50254Y-275735D01* +X48241Y-283909D01* +X47986Y-288130D01* +X-48114D01* +X-50829Y-284184D01* +X-57119Y-278589D01* +X-64563Y-274658D01* +X-72730Y-272618D01* +X-76950Y-272348D01* +X-85304Y-273389D01* +X-93167Y-276394D01* +X-100086Y-281189D01* +X-105659Y-287498D01* +X-107244Y-290524D01* +X-159323D01* +G03X-225250Y-274113I-35006J0D01* +G02X-233473Y-276207I-5153J3044D01* +G03X-266342Y-271453I-20849J-28145D01* +G02X-273696Y-267223I-1556J5803D01* +G03X-289312Y-246428I-33784J-9109D01* +G02X-292194Y-241299I3124J5129D01* +G37* +G36* +X-263488Y-504000D02* +G01X-263321Y-503321D01* +X-263066Y-499100D01* +X-251861D01* +X-252028Y-499779D01* +X-252284Y-504000D01* +X-263488D01* +G37* +G36* +X-248195Y-597550D02* +X-219684D01* +X-219605Y-598200D01* +X-248116D01* +X-248195Y-597550D01* +G37* +G36* +X-226893Y511840D02* +X-217204D01* +X-216191Y503483D01* +X-215176Y500800D01* +X-224866D01* +X-225878Y509157D01* +X-226893Y511840D01* +G37* +G36* +X-183029Y-499760D02* +X79836D01* +X80350Y-504000D01* +X-182516D01* +X-183029Y-499760D01* +G37* +G36* +X-175484Y-323145D02* +G02X-173119Y-318373I5997J0D01* +G03X-163632Y-307350I-21210J27849D01* +G01X-111834D01* +X-110821Y-315707D01* +X-107843Y-323581D01* +X-103071Y-330516D01* +X-96781Y-336111D01* +X-89337Y-340042D01* +X-81170Y-342082D01* +X-76950Y-342352D01* +X-68596Y-341311D01* +X-60733Y-338306D01* +X-53814Y-333511D01* +X-48240Y-327202D01* +X-46762Y-324380D01* +X-28744D01* +X-27731Y-332737D01* +X-24753Y-340611D01* +X-19981Y-347546D01* +X-13691Y-353140D01* +X-6247Y-357072D01* +X1920Y-359112D01* +X6140Y-359382D01* +X14494Y-358341D01* +X22357Y-355336D01* +X29276Y-350541D01* +X34850Y-344232D01* +X38756Y-336775D01* +X40768Y-328600D01* +X41024Y-324380D01* +X182294D01* +X184477Y-330151D01* +X189249Y-337086D01* +X195539Y-342680D01* +X202983Y-346612D01* +X211150Y-348652D01* +X215370Y-348922D01* +X223724Y-347881D01* +X231587Y-344876D01* +X238506Y-340081D01* +X244080Y-333772D01* +X247986Y-326315D01* +X249998Y-318141D01* +X250254Y-313920D01* +X310174D01* +X310787Y-315541D01* +X315559Y-322476D01* +X321849Y-328070D01* +X329293Y-332002D01* +X337460Y-334042D01* +X341680Y-334312D01* +X350034Y-333271D01* +X357897Y-330266D01* +X364816Y-325471D01* +X370390Y-319162D01* +X374296Y-311705D01* +X376308Y-303531D01* +X376564Y-299310D01* +X662023D01* +X667859Y-304500D01* +X675303Y-308432D01* +X683470Y-310472D01* +X687690Y-310742D01* +X696044Y-309701D01* +X703907Y-306696D01* +X710826Y-301900D01* +X716400Y-295592D01* +X720306Y-288134D01* +X722318Y-279960D01* +X722574Y-275740D01* +X757157D01* +G03X812853Y-299295I34715J4460D01* +G02X822450Y-304098I3605J-4785D01* +G01X822450Y-353751D01* +X634860D01* +G03X582878Y-384360I-35003J0D01* +G02X581456Y-395367I-3056J-5201D01* +G03X579838Y-396200I15220J-31550D01* +G01X551434D01* +X550422Y-387843D01* +X547443Y-379969D01* +X542671Y-373034D01* +X536381Y-367439D01* +X528937Y-363508D01* +X520770Y-361467D01* +X516550Y-361198D01* +X508670Y-362180D01* +X436384D01* +X435372Y-353823D01* +X432393Y-345949D01* +X427621Y-339014D01* +X421331Y-333419D01* +X413887Y-329488D01* +X405720Y-327447D01* +X401500Y-327178D01* +X393146Y-328218D01* +X385283Y-331223D01* +X378364Y-336019D01* +X372790Y-342328D01* +X368884Y-349785D01* +X366871Y-357959D01* +X366616Y-362180D01* +X-166973D01* +G03X-174257Y-326780I-33015J11656D01* +G02X-175484Y-323145I4770J3635D01* +G37* +G36* +X-163632Y-307350D02* +G03X-159323Y-290524I-30697J16826D01* +G01X-107244D01* +X-109565Y-294955D01* +X-111578Y-303129D01* +X-111834Y-307350D01* +X-163632D01* +G37* +G36* +X-150402Y-602710D02* +X-150171Y-601771D01* +X-149916Y-597550D01* +X-100667D01* +X-100898Y-598489D01* +X-101154Y-602710D01* +X-150402D01* +G37* +G36* +X-148484Y504400D02* +X-147691Y507619D01* +X-147436Y511840D01* +X-62236D01* +X-63028Y508620D01* +X-63284Y504400D01* +X-148484D01* +G37* +G36* +X-142607Y-701170D02* +G03X-141740Y-693426I-34146J7744D01* +G01X-94521D01* +X-95388Y-696949D01* +X-95644Y-701170D01* +X-142607D01* +G37* +G36* +X-91652Y-15450D02* +X50016D01* +X51028Y-23807D01* +X54007Y-31681D01* +X58779Y-38616D01* +X65069Y-44210D01* +X72513Y-48142D01* +X80680Y-50182D01* +X84900Y-50452D01* +X93254Y-49411D01* +X101117Y-46406D01* +X108036Y-41611D01* +X113610Y-35302D01* +X117516Y-27845D01* +X119528Y-19670D01* +X119784Y-15450D01* +X178010D01* +G03X246977Y-24005I33953J-8555D01* +G01X259393D01* +G03X315285Y-17732I25620J23868D01* +G02X325243Y-18117I4850J-3534D01* +G03X358633Y-34567I29801J18377D01* +G02X365247Y-40444I612J-5971D01* +G03X368260Y-54556I34977J90D01* +G02X364979Y-62573I-5482J-2436D01* +G03X344936Y-83168I12853J-32559D01* +G02X336759Y-86554I-5640J2054D01* +G03X302559Y-85953I-17637J-30275D01* +G02X294591Y-83771I-2834J5292D01* +G03X238330Y-78826I-29940J-18122D01* +G02X229204Y-78704I-4511J3975D01* +G03X177994Y-75864I-26925J-22381D01* +G02X169214Y-75376I-4163J4332D01* +G03X107292Y-98725I-26934J-22356D01* +G02X101463Y-104892I-6022J-146D01* +G01X97897Y-104844D01* +G03X90210Y-105939I1066J-35009D01* +G02X82724Y-99729I-1511J5796D01* +G03X56549Y-131291I-34926J2331D01* +G02X64036Y-137501I1500J-5809D01* +G03X66991Y-154084I35007J-2317D01* +G02X65527Y-158020I-2743J-1220D01* +G03X52049Y-169188I14884J-31679D01* +G01X34862D01* +G03X-34717Y-163698I-35006J0D01* +G02X-42380Y-168119I-5861J1307D01* +G03X-59576Y-167135I-10537J-33404D01* +G02X-66313Y-159584I-964J5921D01* +G03X-65290Y-145561I-33613J9501D01* +G02X-58032Y-139017I5971J675D01* +G03X-60849Y-70182I4831J34673D01* +G02X-67362Y-62085I-917J5930D01* +G03X-91652Y-15450I-32637J12644D01* +G37* +G36* +X-82808Y231451D02* +G02X-81531Y233913I3010J0D01* +G03X-66591Y262412I-20069J28686D01* +G02X-58218Y267560I5980J-343D01* +G03X-9333Y300991I13907J32121D01* +G02X-2712Y307246I6041J238D01* +G03X9555Y310143I-1781J34960D01* +G02X17305Y305878I1920J-5685D01* +G02X17347Y302840I-10874J-1670D01* +G03X82736Y282789I34885J-2883D01* +G02X91833Y284107I5102J-3160D01* +G02X93724Y281402I-9665J-8770D01* +G03X158961Y299056I30230J17654D01* +G01X210974D01* +G02X204368Y293504I-5988J419D01* +G03X195639Y224063I-3618J-34815D01* +G02X200543Y216522I-897J-5949D01* +G03X199269Y207403I33740J-9363D01* +G01X161751D01* +G03X96255Y190206I-35006J0D01* +G02X92079Y181651I-5373J-2674D01* +G03X69021Y129358I6958J-34298D01* +G02X66177Y120982I-5251J-2888D01* +G01X60065Y118310D01* +X54998Y114913D01* +G03X42150Y91405I21922J-27246D01* +G03X41948Y87653I34803J-3752D01* +G01X10593D01* +G03X8792Y113068I-33428J10402D01* +G02X11663Y120648I5574J2223D01* +G03X23948Y172847I-15776J31258D01* +G02X23712Y179289I4953J3407D01* +G02X26882Y182211I13361J-11315D01* +G03X-25431Y226191I-21273J27799D01* +G02X-35505Y225195I-5360J2770D01* +G03X-78198Y228530I-23505J-25964D01* +G02X-82631Y230433I-1472J2685D01* +G02X-82808Y231451I2832J1018D01* +G37* +G36* +X-48114Y-288130D02* +G01X47986D01* +X48998Y-296487D01* +X51977Y-304361D01* +X56749Y-311296D01* +X63039Y-316890D01* +X70483Y-320822D01* +X78650Y-322862D01* +X82870Y-323132D01* +X91224Y-322091D01* +X99087Y-319086D01* +X106006Y-314291D01* +X106334Y-313920D01* +X180486D01* +X181498Y-322277D01* +X182294Y-324380D01* +X41024D01* +X40012Y-316023D01* +X37033Y-308149D01* +X32261Y-301214D01* +X25971Y-295619D01* +X18527Y-291688D01* +X10360Y-289647D01* +X6140Y-289378D01* +X-2214Y-290418D01* +X-10077Y-293423D01* +X-16996Y-298219D01* +X-22570Y-304528D01* +X-24048Y-307350D01* +X-42066D01* +X-43078Y-298993D01* +X-46057Y-291119D01* +X-48114Y-288130D01* +G37* +G36* +X-46762Y-324380D02* +X-44334Y-319745D01* +X-42321Y-311571D01* +X-42066Y-307350D01* +X-24048D01* +X-26476Y-311985D01* +X-28488Y-320159D01* +X-28744Y-324380D01* +X-46762D01* +G37* +G36* +X-38020Y611480D02* +X-15050D01* +G03X-12084Y597374I35025J0D01* +G01X-35052D01* +G03X-38020Y611480I-35001J0D01* +G37* +G36* +X-31607Y-606370D02* +G01X-31386Y-602710D01* +X-15132D01* +X-15354Y-606370D01* +X-31607D01* +G37* +G36* +X-26192Y-705640D02* +X-26131Y-705391D01* +X-25876Y-701170D01* +X-7657D01* +X-7718Y-701419D01* +X-7974Y-705640D01* +X-26192D01* +G37* +G36* +X6184Y500000D02* +X6228Y500179D01* +X6484Y504400D01* +X14725D01* +X14681Y504221D01* +X14426Y500000D01* +X6184D01* +G37* +G36* +X36454Y30778D02* +X173415D01* +G03X174268Y23100I35003J0D01* +G01X37384D01* +X36454Y30778D01* +G37* +G36* +X53903Y-602150D02* +X100596D01* +X101107Y-606370D01* +X54414D01* +X53903Y-602150D01* +G37* +G36* +X60991Y-699014D02* +X106696D01* +G03X107329Y-705640I35000J0D01* +G01X61794D01* +X60991Y-699014D01* +G37* +G36* +X83264Y507675D02* +X144148D01* +G03X145000Y500000I35000J0D01* +G01X84194D01* +X83264Y507675D01* +G37* +G36* +X106334Y-313920D02* +X111580Y-307982D01* +X115486Y-300525D01* +X117498Y-292350D01* +X117754Y-288130D01* +X191906D01* +X186660Y-294068D01* +X182754Y-301525D01* +X180741Y-309699D01* +X180486Y-313920D01* +X106334D01* +G37* +G36* +X145856Y-514980D02* +X147336Y-512155D01* +X149348Y-503980D01* +X149604Y-499760D01* +X454564D01* +X453084Y-502585D01* +X451071Y-510759D01* +X450816Y-514980D01* +X145856D01* +G37* +G36* +X169318Y-609580D02* +X170108Y-606370D01* +X170364Y-602150D01* +X186711D01* +X185921Y-605359D01* +X185666Y-609580D01* +X169318D01* +G37* +G36* +X171739Y603256D02* +X184998D01* +G03X185063Y601110I35006J0D01* +G01X171805D01* +G03X171739Y603256I-35012J1D01* +G37* +G36* +X246876Y-299310D02* +G01X306796D01* +X307808Y-307667D01* +X310174Y-313920D01* +X250254D01* +X249242Y-305563D01* +X246876Y-299310D01* +G37* +G36* +X253962Y-600009D02* +X315987D01* +G03X317321Y-609580I35006J0D01* +G01X255434D01* +X254421Y-601223D01* +X253962Y-600009D01* +G37* +G36* +X367347Y-275740D02* +X652806D01* +X653818Y-284097D01* +X656797Y-291971D01* +X661569Y-298906D01* +X662023Y-299310D01* +X376564D01* +X375552Y-290953D01* +X372573Y-283079D01* +X367801Y-276144D01* +X367347Y-275740D01* +G37* +G36* +X386318Y-698400D02* +G03X386420Y-695720I-34899J2681D01* +G01X415278D01* +X415116Y-698400D01* +X386318D01* +G37* +G36* +X409061Y-112304D02* +G02X409419Y-110264I5995J0D01* +G03X412376Y-89501I-31620J15095D01* +G02X417888Y-82550I5929J960D01* +G01X565974Y-72343D01* +X565984Y-72347D01* +G03X635463Y-76893I35016J1951D01* +G01X662699Y-41555D01* +X662708Y-41550D01* +X664956Y-41471D01* +G02X670460Y-50286I199J-6002D01* +G03X727203Y-48297I29090J-19510D01* +G02X732084Y-39123I5091J3177D01* +G01X761599Y-38090D01* +G02X766906Y-47250I195J-6004D01* +G03X813554Y-96349I29745J-18450D01* +G02X822450Y-101605I2890J-5265D01* +G01Y-110938D01* +G02X813490Y-116155I-5996J-6D01* +G03X767667Y-166850I-17272J-30445D01* +G01X733334D01* +X732322Y-158493D01* +X729343Y-150619D01* +X724571Y-143684D01* +X718281Y-138089D01* +X710837Y-134158D01* +X702670Y-132117D01* +X698450Y-131848D01* +X690096Y-132889D01* +X682233Y-135894D01* +X675314Y-140689D01* +X669740Y-146998D01* +X665834Y-154455D01* +X663821Y-162629D01* +X663566Y-166850D01* +X450317D01* +G03X443509Y-164240I-15865J-31201D01* +G02X439139Y-157493I1580J5812D01* +G03X413529Y-118101I-34566J5549D01* +G02X409061Y-112304I1527J5797D01* +G37* +G36* +X409380Y-396200D02* +G01X409854Y-396141D01* +X417717Y-393136D01* +X424636Y-388341D01* +X430210Y-382032D01* +X434116Y-374575D01* +X436128Y-366401D01* +X436384Y-362180D01* +X508670D01* +X508196Y-362239D01* +X500333Y-365244D01* +X493414Y-370039D01* +X487840Y-376348D01* +X483934Y-383805D01* +X481921Y-391979D01* +X481666Y-396200D01* +X409380D01* +G37* +G36* +X479366Y-679950D02* +X579566D01* +X580578Y-688307D01* +X583557Y-696181D01* +X585084Y-698400D01* +X484884D01* +X483871Y-690043D01* +X480893Y-682169D01* +X479366Y-679950D01* +G37* +G36* +X490856Y-607050D02* +G03X491981Y-598248I-33878J8802D01* +G01X500049D01* +X498921Y-602829D01* +X498666Y-607050D01* +X490856D01* +G37* +G36* +X510554Y-490687D02* +X635359D01* +G03X645159Y-514980I35009J0D01* +G01X520584D01* +X519571Y-506623D01* +X516593Y-498749D01* +X511821Y-491814D01* +X510554Y-490687D01* +G37* +G36* +X533145Y-426894D02* +X539686Y-422360D01* +X545260Y-416052D01* +X549166Y-408594D01* +X551178Y-400420D01* +X551434Y-396200D01* +X579838D01* +G03X561745Y-424293I16838J-30717D01* +G03X561648Y-426894I34904J-2601D01* +G01X533145D01* +G37* +G36* +X566455Y-596137D02* +X616300D01* +G03X618044Y-607050I35005J0D01* +G01X568434D01* +X567421Y-598693D01* +X566455Y-596137D01* +G37* +G36* +X610679Y-391095D02* +G02X615054Y-385283I6047J0D01* +G03X634860Y-353751I-15197J31532D01* +G01X822450D01* +Y-393300D01* +X766234D01* +X765222Y-384943D01* +X762243Y-377069D01* +X757471Y-370134D01* +X751181Y-364539D01* +X743737Y-360608D01* +X735570Y-358567D01* +X731350Y-358298D01* +X722996Y-359339D01* +X715133Y-362344D01* +X708214Y-367139D01* +X702640Y-373448D01* +X698734Y-380905D01* +X696721Y-389079D01* +X696466Y-393300D01* +X611096D01* +G02X610679Y-391095I5630J2206D01* +G37* +G36* +X648911Y-684850D02* +G01X649078Y-684170D01* +X649334Y-679950D01* +X683738D01* +X683571Y-680629D01* +X683316Y-684850D01* +X648911D01* +G37* +G36* +X611267Y-393141D02* +X696307D01* +G02X696307Y-393459I0J-159D01* +G01X611267D01* +G02X611267Y-393141I0J159D01* +G37* +G36* +X766393D02* +G01X822291D01* +G02X822291Y-393459I0J-159D01* +G01X766393D01* +G02X766393Y-393141I0J159D01* +G37* +G36* +X649074Y-684691D02* +G01X683157D01* +G02X683157Y-685009I0J-159D01* +G01X649074D01* +G02X649074Y-684691I0J159D01* +G37* +G36* +X753243D02* +G01X822290D01* +G02X822290Y-685009I0J-159D01* +G01X753243D01* +G02X753243Y-684691I0J159D01* +G37* +G36* +X450665Y-166691D02* +G01X663407D01* +G02X663407Y-167009I0J-159D01* +G01X450665D01* +G02X450665Y-166691I0J159D01* +G37* +G36* +X733493D02* +G01X767473D01* +G02X767473Y-167009I0J-159D01* +G01X733493D01* +G02X733493Y-166691I0J159D01* +G37* +G36* +X367585Y-275581D02* +G01X652647D01* +G02X652647Y-275899I0J-159D01* +G01X367585D01* +G02X367585Y-275581I0J159D01* +G37* +G36* +X722733D02* +G01X756997D01* +G02X756997Y-275899I0J-159D01* +G01X722733D01* +G02X722733Y-275581I0J159D01* +G37* +G36* +X759012Y-489233D02* +G01X822290D01* +G02X822290Y-489551I0J-159D01* +G01X759012D01* +G02X759012Y-489233I0J159D01* +G37* +G36* +X510793Y-490528D02* +G01X635200D01* +G02X635200Y-490846I0J-159D01* +G01X510793D01* +G02X510793Y-490528I0J159D01* +G37* +G36* +X757111Y-585890D02* +G01X822290D01* +G02X822290Y-586208I0J-159D01* +G01X757111D01* +G02X757111Y-585890I0J159D01* +G37* +G36* +X566624Y-595978D02* +G01X616141D01* +G02X616141Y-596296I0J-159D01* +G01X566624D01* +G02X566624Y-595978I0J159D01* +G37* +G36* +X479559Y-679791D02* +G01X579407D01* +G02X579407Y-680109I0J-159D01* +G01X479559D01* +G02X479559Y-679791I0J159D01* +G37* +G36* +X649493D02* +G01X683575D01* +G02X683575Y-680109I0J-159D01* +G01X649493D01* +G02X649493Y-679791I0J159D01* +G37* +G36* +X635019Y-353592D02* +G01X822291D01* +G02X822291Y-353910I0J-159D01* +G01X635019D01* +G02X635019Y-353592I0J159D01* +G37* +G36* +X533424Y-426735D02* +G01X561490D01* +G02X561490Y-427053I0J-159D01* +G01X533424D01* +G02X533424Y-426735I0J159D01* +G37* +G36* +X491020Y-606891D02* +G01X498507D01* +G02X498507Y-607209I0J-159D01* +G01X491020D01* +G02X491020Y-606891I0J159D01* +G37* +G36* +X568593D02* +G01X617877D01* +G02X617877Y-607209I0J-159D01* +G01X568593D01* +G02X568593Y-606891I0J159D01* +G37* +G36* +X410145Y-396041D02* +G01X481507D01* +G02X481507Y-396359I0J-159D01* +G01X410145D01* +G02X410145Y-396041I0J159D01* +G37* +G36* +X551593D02* +G01X579510D01* +G02X579510Y-396359I0J-159D01* +G01X551593D01* +G02X551593Y-396041I0J159D01* +G37* +G36* +X146036Y-514821D02* +G01X450657D01* +G02X450657Y-515139I0J-159D01* +G01X146036D01* +G02X146036Y-514821I0J159D01* +G37* +G36* +X520743D02* +G01X644939D01* +G02X644939Y-515139I0J-159D01* +G01X520743D01* +G02X520743Y-514821I0J159D01* +G37* +G36* +X386477Y-698241D02* +G01X414957D01* +G02X414957Y-698559I0J-159D01* +G01X386477D01* +G02X386477Y-698241I0J159D01* +G37* +G36* +X485043D02* +G01X584891D01* +G02X584891Y-698559I0J-159D01* +G01X485043D01* +G02X485043Y-698241I0J159D01* +G37* +G36* +X-166805Y-362021D02* +G01X366457D01* +G02X366457Y-362339I0J-159D01* +G01X-166805D01* +G02X-166805Y-362021I0J159D01* +G37* +G36* +X436543D02* +G01X507905D01* +G02X507905Y-362339I0J-159D01* +G01X436543D01* +G02X436543Y-362021I0J159D01* +G37* +G36* +X492140Y-598089D02* +G01X499886D01* +G02X499886Y-598407I0J-159D01* +G01X492140D01* +G02X492140Y-598089I0J159D01* +G37* +G36* +X254132Y-599851D02* +G01X315828D01* +G02X315828Y-600168I0J-159D01* +G01X254132D01* +G02X254132Y-599851I0J159D01* +G37* +G36* +X247046Y-299151D02* +G01X306637D01* +G02X306637Y-299469I0J-159D01* +G01X247046D01* +G02X247046Y-299151I0J159D01* +G37* +G36* +X376723D02* +G01X661784D01* +G02X661784Y-299469I0J-159D01* +G01X376723D01* +G02X376723Y-299151I0J159D01* +G37* +G36* +X413174Y712325D02* +G01X477900D01* +G02X477900Y712008I0J-159D01* +G01X413174D01* +G02X413174Y712325I0J159D01* +G37* +G36* +X221265Y707330D02* +G01X234761D01* +G02X234761Y707013I0J-159D01* +G01X221265D01* +G02X221265Y707330I0J159D01* +G37* +G36* +X169482Y-609421D02* +G01X185507D01* +G02X185507Y-609739I0J-159D01* +G01X169482D01* +G02X169482Y-609421I0J159D01* +G37* +G36* +X255593D02* +G01X317155D01* +G02X317155Y-609739I0J-159D01* +G01X255593D01* +G02X255593Y-609421I0J159D01* +G37* +G36* +X373708Y597296D02* +G01X380372D01* +G02X380372Y596978I0J-159D01* +G01X373708D01* +G02X373708Y597296I0J159D01* +G37* +G36* +X171898Y603415D02* +G01X184839D01* +G02X184839Y603098I0J-159D01* +G01X171898D01* +G02X171898Y603415I0J159D01* +G37* +G36* +X106546Y-313761D02* +G01X180327D01* +G02X180327Y-314079I0J-159D01* +G01X106546D01* +G02X106546Y-313761I0J159D01* +G37* +G36* +X250413D02* +G01X310004D01* +G02X310004Y-314079I0J-159D01* +G01X250413D01* +G02X250413Y-313761I0J159D01* +G37* +G36* +X247136Y-23846D02* +G01X259176D01* +G02X259176Y-24164I0J-159D01* +G01X247136D01* +G02X247136Y-23846I0J159D01* +G37* +G36* +X36614Y30936D02* +G01X173257D01* +G02X173257Y30619I0J-159D01* +G01X36614D01* +G02X36614Y30936I0J159D01* +G37* +G36* +X285166Y500158D02* +G01X403271D01* +G02X403271Y499840I0J-159D01* +G01X285166D01* +G02X285166Y500158I0J159D01* +G37* +G36* +X83424Y507833D02* +G01X143989D01* +G02X143989Y507516I0J-159D01* +G01X83424D01* +G02X83424Y507833I0J159D01* +G37* +G36* +X386579Y-695560D02* +G01X415119D01* +G02X415119Y-695878I0J-159D01* +G01X386579D01* +G02X386579Y-695560I0J159D01* +G37* +G36* +X61151Y-698856D02* +G01X106537D01* +G02X106537Y-699173I0J-159D01* +G01X61151D01* +G02X61151Y-698856I0J159D01* +G37* +G36* +X54062Y-601991D02* +G01X100437D01* +G02X100437Y-602309I0J-159D01* +G01X54062D01* +G02X54062Y-601991I0J159D01* +G37* +G36* +X170523D02* +G01X186548D01* +G02X186548Y-602309I0J-159D01* +G01X170523D01* +G02X170523Y-601991I0J159D01* +G37* +G36* +X-182870Y-499601D02* +G01X79677D01* +G02X79677Y-499919I0J-159D01* +G01X-182870D01* +G02X-182870Y-499601I0J159D01* +G37* +G36* +X149763D02* +G01X454384D01* +G02X454384Y-499919I0J-159D01* +G01X149763D01* +G02X149763Y-499601I0J159D01* +G37* +G36* +X-91009Y-15291D02* +G01X49857D01* +G02X49857Y-15609I0J-159D01* +G01X-91009D01* +G02X-91009Y-15291I0J159D01* +G37* +G36* +X119943D02* +G01X177846D01* +G02X177846Y-15609I0J-159D01* +G01X119943D01* +G02X119943Y-15291I0J159D01* +G37* +G36* +X-47921Y-287971D02* +G01X47827D01* +G02X47827Y-288289I0J-159D01* +G01X-47921D01* +G02X-47921Y-287971I0J159D01* +G37* +G36* +X117913D02* +G01X191695D01* +G02X191695Y-288289I0J-159D01* +G01X117913D01* +G02X117913Y-287971I0J159D01* +G37* +G36* +X161910Y207562D02* +G01X199110D01* +G02X199110Y207245I0J-159D01* +G01X161910D01* +G02X161910Y207562I0J159D01* +G37* +G36* +X10759Y87812D02* +G01X41789D01* +G02X41789Y87494I0J-159D01* +G01X10759D01* +G02X10759Y87812I0J159D01* +G37* +G36* +X6347Y500159D02* +G01X14267D01* +G02X14267Y499841I0J-159D01* +G01X6347D01* +G02X6347Y500159I0J159D01* +G37* +G36* +X84353D02* +G01X144837D01* +G02X144837Y499841I0J-159D01* +G01X84353D01* +G02X84353Y500159I0J159D01* +G37* +G36* +X-26029Y-705481D02* +G01X-8133D01* +G02X-8133Y-705799I0J-159D01* +G01X-26029D01* +G02X-26029Y-705481I0J159D01* +G37* +G36* +X61953D02* +G01X107167D01* +G02X107167Y-705799I0J-159D01* +G01X61953D01* +G02X61953Y-705481I0J159D01* +G37* +G36* +X171964Y601269D02* +G01X184904D01* +G02X184904Y600951I0J-159D01* +G01X171964D01* +G02X171964Y601269I0J159D01* +G37* +G36* +X-37847Y611639D02* +G01X-15209D01* +G02X-15209Y611321I0J-159D01* +G01X-37847D01* +G02X-37847Y611639I0J159D01* +G37* +G36* +X-31448Y-606211D02* +G01X-15513D01* +G02X-15513Y-606529I0J-159D01* +G01X-31448D01* +G02X-31448Y-606211I0J159D01* +G37* +G36* +X54573D02* +G01X100947D01* +G02X100947Y-606529I0J-159D01* +G01X54573D01* +G02X54573Y-606211I0J159D01* +G37* +G36* +X-46582Y-324221D02* +G01X-28903D01* +G02X-28903Y-324539I0J-159D01* +G01X-46582D01* +G02X-46582Y-324221I0J159D01* +G37* +G36* +X41183D02* +G01X182124D01* +G02X182124Y-324539I0J-159D01* +G01X41183D01* +G02X41183Y-324221I0J159D01* +G37* +G36* +X-205328Y23259D02* +G01X-32543D01* +G02X-32543Y22941I0J-159D01* +G01X-205328D01* +G02X-205328Y23259I0J159D01* +G37* +G36* +X37543D02* +G01X174105D01* +G02X174105Y22941I0J-159D01* +G01X37543D01* +G02X37543Y23259I0J159D01* +G37* +G36* +X-148320Y504559D02* +G01X-63443D01* +G02X-63443Y504241I0J-159D01* +G01X-148320D01* +G02X-148320Y504559I0J159D01* +G37* +G36* +X6643D02* +G01X14562D01* +G02X14562Y504241I0J-159D01* +G01X6643D01* +G02X6643Y504559I0J159D01* +G37* +G36* +X-142445Y-701011D02* +G01X-95803D01* +G02X-95803Y-701329I0J-159D01* +G01X-142445D01* +G02X-142445Y-701011I0J159D01* +G37* +G36* +X-25717D02* +G01X-7820D01* +G02X-7820Y-701329I0J-159D01* +G01X-25717D01* +G02X-25717Y-701011I0J159D01* +G37* +G36* +X-150239Y-602551D02* +G01X-101313D01* +G02X-101313Y-602869I0J-159D01* +G01X-150239D01* +G02X-150239Y-602551I0J159D01* +G37* +G36* +X-31227D02* +G01X-15291D01* +G02X-15291Y-602869I0J-159D01* +G01X-31227D01* +G02X-31227Y-602551I0J159D01* +G37* +G36* +X-163451Y-307191D02* +G01X-111993D01* +G02X-111993Y-307509I0J-159D01* +G01X-163451D01* +G02X-163451Y-307191I0J159D01* +G37* +G36* +X-41907D02* +G01X-24228D01* +G02X-24228Y-307509I0J-159D01* +G01X-41907D01* +G02X-41907Y-307191I0J159D01* +G37* +G36* +X159120Y299214D02* +G01X210816D01* +G02X210816Y298897I0J-159D01* +G01X159120D01* +G02X159120Y299214I0J159D01* +G37* +G36* +X-220229Y102608D02* +G01X-159841D01* +G02X-159841Y102290I0J-159D01* +G01X-220229D01* +G02X-220229Y102608I0J159D01* +G37* +G36* +X35021Y-169030D02* +G01X51853D01* +G02X51853Y-169347I0J-159D01* +G01X35021D01* +G02X35021Y-169030I0J159D01* +G37* +G36* +X-236716Y-202281D02* +G01X-188110D01* +G02X-188110Y-202598I0J-159D01* +G01X-236716D01* +G02X-236716Y-202281I0J159D01* +G37* +G36* +X-226723Y511999D02* +G01X-217363D01* +G02X-217363Y511681I0J-159D01* +G01X-226723D01* +G02X-226723Y511999I0J159D01* +G37* +G36* +X-147277D02* +G01X-62399D01* +G02X-62399Y511681I0J-159D01* +G01X-147277D01* +G02X-147277Y511999I0J159D01* +G37* +G36* +X-248035Y-597391D02* +G01X-219843D01* +G02X-219843Y-597709I0J-159D01* +G01X-248035D01* +G02X-248035Y-597391I0J159D01* +G37* +G36* +X-149757D02* +G01X-100830D01* +G02X-100830Y-597709I0J-159D01* +G01X-149757D01* +G02X-149757Y-597391I0J159D01* +G37* +G36* +X-34893Y597533D02* +G01X-12257D01* +G02X-12257Y597216I0J-159D01* +G01X-34893D01* +G02X-34893Y597533I0J159D01* +G37* +G36* +X-327537Y614370D02* +G01X-221600D01* +G02X-221600Y614053I0J-159D01* +G01X-327537D01* +G02X-327537Y614370I0J159D01* +G37* +G36* +X-142754Y307876D02* +G01X-121797D01* +G02X-121797Y307558I0J-159D01* +G01X-142754D01* +G02X-142754Y307876I0J159D01* +G37* +G36* +X-321160Y237687D02* +G01X-236731D01* +G02X-236731Y237370I0J-159D01* +G01X-321160D01* +G02X-321160Y237687I0J159D01* +G37* +G36* +X-263325Y-503841D02* +G01X-252443D01* +G02X-252443Y-504159I0J-159D01* +G01X-263325D01* +G02X-263325Y-503841I0J159D01* +G37* +G36* +X-182357D02* +G01X80190D01* +G02X80190Y-504159I0J-159D01* +G01X-182357D01* +G02X-182357Y-503841I0J159D01* +G37* +G36* +X-141581Y-693267D02* +G01X-94684D01* +G02X-94684Y-693585I0J-159D01* +G01X-141581D01* +G02X-141581Y-693267I0J159D01* +G37* +G36* +X-326960Y-697696D02* +G01X-282662D01* +G02X-282662Y-698014I0J-159D01* +G01X-326960D01* +G02X-326960Y-697696I0J159D01* +G37* +G36* +X-327063Y500959D02* +G01X-294793D01* +G02X-294793Y500641I0J-159D01* +G01X-327063D01* +G02X-327063Y500959I0J159D01* +G37* +G36* +X-224707D02* +G01X-215346D01* +G02X-215346Y500641I0J-159D01* +G01X-224707D01* +G02X-224707Y500959I0J159D01* +G37* +G36* +X-327918Y-598041D02* +G01X-318043D01* +G02X-318043Y-598359I0J-159D01* +G01X-327918D01* +G02X-327918Y-598041I0J159D01* +G37* +G36* +X-247957D02* +G01X-219765D01* +G02X-219765Y-598359I0J-159D01* +G01X-247957D01* +G02X-247957Y-598041I0J159D01* +G37* +G36* +X-327387Y578579D02* +G01X-320123D01* +G02X-320123Y578261I0J-159D01* +G01X-327387D01* +G02X-327387Y578579I0J159D01* +G37* +G36* +X-250037D02* +G01X-170760D01* +G02X-170760Y578261I0J-159D01* +G01X-250037D01* +G02X-250037Y578579I0J159D01* +G37* +G36* +X-464804Y-498941D02* +G01X-332993D01* +G02X-332993Y-499259I0J-159D01* +G01X-464804D01* +G02X-464804Y-498941I0J159D01* +G37* +G36* +X-262907D02* +G01X-252024D01* +G02X-252024Y-499259I0J-159D01* +G01X-262907D01* +G02X-262907Y-498941I0J159D01* +G37* +G36* +X-434973Y-697641D02* +G01X-397043D01* +G02X-397043Y-697959I0J-159D01* +G01X-434973D01* +G02X-434973Y-697641I0J159D01* +G37* +G36* +X-326957D02* +G01X-282662D01* +G02X-282662Y-697959I0J-159D01* +G01X-326957D01* +G02X-326957Y-697641I0J159D01* +G37* +G36* +X-488724Y-598031D02* +G01X-398003D01* +G02X-398003Y-598349I0J-159D01* +G01X-488724D01* +G02X-488724Y-598031I0J159D01* +G37* +G36* +X-327917D02* +G01X-318042D01* +G02X-318042Y-598349I0J-159D01* +G01X-327917D01* +G02X-327917Y-598031I0J159D01* +G37* +G36* +X-470143Y-387641D02* +G01X-448393D01* +G02X-448393Y-387959I0J-159D01* +G01X-470143D01* +G02X-470143Y-387641I0J159D01* +G37* +G36* +X-378307D02* +G01X377900D01* +G02X377900Y-387959I0J-159D01* +G01X-378307D01* +G02X-378307Y-387641I0J159D01* +G37* +G36* +X-159165Y-290365D02* +G01X-107424D01* +G02X-107424Y-290683I0J-159D01* +G01X-159165D01* +G02X-159165Y-290365I0J159D01* +G37* +G36* +X-792467Y-293213D02* +G01X-458058D01* +G02X-458058Y-293530I0J-159D01* +G01X-792467D01* +G02X-792467Y-293213I0J159D01* +G37* +G36* +X-541173Y-692141D02* +G01X-504493D01* +G02X-504493Y-692459I0J-159D01* +G01X-541173D01* +G02X-541173Y-692141I0J159D01* +G37* +G36* +X-434407D02* +G01X-396476D01* +G02X-396476Y-692459I0J-159D01* +G01X-434407D01* +G02X-434407Y-692141I0J159D01* +G37* +G36* +X-620836Y-365871D02* +G01X-532413D01* +G02X-532413Y-366189I0J-159D01* +G01X-620836D01* +G02X-620836Y-365871I0J159D01* +G37* +G36* +X-462327D02* +G01X-440577D01* +G02X-440577Y-366189I0J-159D01* +G01X-462327D01* +G02X-462327Y-365871I0J159D01* +G37* +G36* +X-463889Y-460889D02* +G01X588302D01* +G02X588302Y-461207I0J-159D01* +G01X-463889D01* +G02X-463889Y-460889I0J159D01* +G37* +G36* +X-543701Y-505899D02* +G01X-534451D01* +G02X-534451Y-506217I0J-159D01* +G01X-543701D01* +G02X-543701Y-505899I0J159D01* +G37* +G36* +X-659900Y-158169D02* +G01X-431613D01* +G02X-431613Y-158486I0J-159D01* +G01X-659900D01* +G02X-659900Y-158169I0J159D01* +G37* +G36* +X-766381Y-233695D02* +G01X-737831D01* +G02X-737831Y-234013I0J-159D01* +G01X-766381D01* +G02X-766381Y-233695I0J159D01* +G37* +G36* +X-815200Y-751279D02* +G01X-815199Y-599851D01* +X-772852D01* +G03X-737170Y-634857I35012J0D01* +G02X-732721Y-644527I-291J-5992D01* +G03X-699427Y-702817I25350J-24174D01* +G02X-692944Y-706995I749J-5958D01* +G03X-623549Y-700107I34356J6888D01* +G01X-612726D01* +G03X-600370Y-735445I34132J-7894D01* +G01X-599747Y-816870D01* +G02X-605830Y-822915I-6003J-43D01* +G01X-659051Y-822174D01* +G02X-662513Y-811334I69J5995D01* +G03X-704665Y-810748I-20688J28232D01* +G02X-708428Y-821486I-3692J-4735D01* +G01X-757444Y-820804D01* +G02X-761151Y-810154I88J6001D01* +G03X-805337Y-755869I-21649J27503D01* +G02X-815176Y-751807I-3861J4594D01* +G01X-815200Y-751279D01* +G37* +G36* +X-815199Y-599851D02* +X-815199Y-562051D01* +X-810915Y-558676D01* +G03X-758248Y-517181I19949J28851D01* +G01X-741898Y-504301D01* +X-711261Y-500999D01* +X-711245Y-500987D01* +X-696901Y-465003D01* +X-669499Y-430992D01* +X-662296Y-335003D01* +X-662289Y-335000D01* +X-634308Y-336001D01* +X-634302Y-336004D01* +X-634299Y-336011D01* +X-630098Y-409989D01* +X-630087Y-410006D01* +X-629398Y-410321D01* +X-629397Y-410326D01* +X-629024Y-420487D01* +X-629003Y-420506D01* +X-609087Y-419488D01* +X-603151Y-422168D01* +X-601754Y-423797D01* +X-602344Y-557257D01* +X-574053Y-589997D01* +X-574051Y-590006D01* +X-577653Y-620004D01* +X-603848Y-653005D01* +Y-653010D01* +X-600900Y-666000D01* +X-600790Y-680897D01* +G03X-612726Y-700107I22196J-27105D01* +G01X-623549D01* +G03X-666543Y-665983I-35039J0D01* +G02X-673159Y-661299I-740J5970D01* +G03X-708050Y-633693I-34213J-7390D01* +G02X-712161Y-623624I295J5994D01* +G03X-772746Y-597130I-25689J23775D01* +G03X-772852Y-599851I34906J-2721D01* +G01X-815199D01* +G37* +G36* +X-623391Y-699949D02* +X-612889D01* +G02X-612889Y-700266I0J-159D01* +G01X-623391D01* +G02X-623391Y-699949I0J159D01* +G37* +G36* +X-815040Y-599693D02* +G01X-773011D01* +G02X-773011Y-600010I0J-159D01* +G01X-815040D01* +G02X-815040Y-599693I0J159D01* +G37* +G36* +X313531Y354562D02* +G01X313532Y354566D01* +X313955Y355448D01* +X324649Y362207D01* +G03X349901Y377603I-3899J34801D01* +G01X557709D01* +G03X621728Y397176I35002J0D01* +G02X621536Y399940I2565J1567D01* +G02X623329Y401940I8853J-6133D01* +G03X634101Y427200I-24231J25260D01* +G01X671995D01* +X672839Y424969D01* +X677611Y418034D01* +X683901Y412439D01* +X691345Y408508D01* +X699512Y406468D01* +X703850Y406198D01* +X712207Y407210D01* +X720081Y410189D01* +X727015Y414961D01* +X732610Y421251D01* +X736542Y428695D01* +X738582Y436862D01* +X738852Y441200D01* +X824012D01* +X823819Y271250D01* +X745204D01* +G03X713925Y306053I-35001J0D01* +G02X711284Y309130I360J2981D01* +G03X710684Y321311I-34727J4395D01* +G02X712609Y324652I2964J518D01* +G03X666466Y349769I-12011J32878D01* +G02X664541Y346428I-2935J-534D01* +G03X644354Y299833I12017J-32877D01* +G01X480857D01* +G03X426908Y329253I-34996J0D01* +G02X418023Y332539I-3140J5166D01* +G03X352283Y320888I-31032J-16193D01* +G03X351989Y316357I34712J-4531D01* +G01X340959D01* +G03X317642Y330402I-28337J-20667D01* +G01X313531Y354562D01* +G37* +G36* +X328632Y264485D02* +G03X340959Y316357I-16010J31205D01* +G01X351989D01* +G03X405952Y286927I35007J0D01* +G02X414837Y283640I3138J-5169D01* +G03X480857Y299833I31024J16194D01* +G01X644354D01* +G03X672825Y278747I32204J13718D01* +G02X675226Y276947I-356J-2976D01* +G02X675306Y273996I-9893J-1745D01* +G03X676500Y261780I34857J-2760D01* +G02X674763Y258338I-2920J-686D01* +G03X654438Y233990I13802J-32179D01* +G01X637632D01* +X636619Y242347D01* +X633641Y250221D01* +X628869Y257156D01* +X622579Y262751D01* +X615135Y266682D01* +X606967Y268722D01* +X602630Y268992D01* +X594273Y267980D01* +X586399Y265001D01* +X579464Y260229D01* +X573869Y253939D01* +X569938Y246495D01* +X567898Y238328D01* +X567628Y233990D01* +X346221D01* +G03X330213Y255186I-33873J-8939D01* +G01X328632Y264485D01* +G37* +G36* +X339178Y202525D02* +G03X346221Y233990I-26830J22526D01* +G01X567628D01* +X568640Y225633D01* +X571619Y217759D01* +X576391Y210824D01* +X582681Y205229D01* +X590125Y201298D01* +X598292Y199258D01* +X602630Y198988D01* +X610987Y200000D01* +X618861Y202979D01* +X625795Y207751D01* +X631390Y214041D01* +X635322Y221485D01* +X637362Y229652D01* +X637632Y233990D01* +X654438D01* +G03X675080Y193847I34127J-7831D01* +G02X677356Y185299I-2784J-5318D01* +G03X675293Y151275I29481J-18862D01* +G03X662358Y133686I20385J-28542D01* +G02X653534Y131111I-5492J2415D01* +G03X604465Y120653I-19443J-29118D01* +G03X552322Y94667I-17415J-30363D01* +G03X552047Y90286I34733J-4381D01* +G01X473369D01* +G03X439745Y133870I-33933J8583D01* +G02X434387Y142457I56J6000D01* +G03X402676Y122950I-31382J15487D01* +G02X408011Y114317I-59J-6002D01* +G03X404488Y96654I31411J-15448D01* +G02X398719Y90279I-5991J-376D01* +G03X370279Y73838I1265J-35006D01* +G02X359638Y76437I-4738J3684D01* +G01X355606Y98441D01* +G03X351265Y122104I-34521J5897D01* +G01X340781Y179291D01* +X341402Y189445D01* +X339178Y202525D01* +G37* +G36* +X346544Y423516D02* +X349030Y428708D01* +X368675Y457213D01* +X386044Y470600D01* +X386048Y470608D01* +X386050Y470616D01* +X386049Y471822D01* +X386054Y471831D01* +X405594Y482636D01* +X410166Y490970D01* +X436418D01* +X437430Y482613D01* +X440409Y474739D01* +X445181Y467804D01* +X451471Y462209D01* +X458915Y458278D01* +X467082Y456238D01* +X471420Y455968D01* +X479777Y456980D01* +X487651Y459959D01* +X494585Y464731D01* +X500180Y471021D01* +X504112Y478465D01* +X506152Y486632D01* +X506422Y490970D01* +X640085D01* +G03X696627Y486950I29729J18496D01* +G02X700454Y487416I2191J-2046D01* +G03X754552Y516753I19094J29337D01* +G01X824099D01* +X824012Y441200D01* +X738852D01* +X737839Y449557D01* +X734861Y457431D01* +X730089Y464366D01* +X723799Y469961D01* +X716355Y473892D01* +X708188Y475932D01* +X703850Y476202D01* +X695493Y475190D01* +X687619Y472211D01* +X680684Y467439D01* +X675089Y461149D01* +X671158Y453705D01* +X669118Y445538D01* +X668848Y441200D01* +X631179D01* +G03X570081Y407624I-32081J-14000D01* +G02X570274Y404860I-2574J-1568D01* +G02X568481Y402860I-8870J6149D01* +G03X557913Y381375I24242J-25265D01* +G03X557709Y377603I34798J-3772D01* +G01X349901D01* +G03X346567Y420668I-29150J19405D01* +G01X346544Y423516D01* +G37* +G36* +X385303Y824194D02* +X385310Y824199D01* +X554613Y824316D01* +G02X558340Y813612I0J-6001D01* +G03X567651Y753456I21738J-27434D01* +G01X569583Y750654D01* +X568945Y746972D01* +G03X616026Y774777I34659J-4923D01* +G01X614097Y777576D01* +X614096Y777581D01* +X614735Y781257D01* +G03X601383Y813986I-34712J4927D01* +G02X605498Y824350I4115J4365D01* +G01X824444Y824497D01* +X824449Y824491D01* +X824213Y617657D01* +X752948D01* +G03X690817Y639783I-35006J0D01* +G03X637042Y612866I-18870J-29477D01* +G03X636947Y610292I34911J-2574D01* +G01X599537D01* +G03X532994Y618961I-34560J-5552D01* +G02X530753Y617331I-2708J1368D01* +G02X528115Y617788I554J11041D01* +G03X484640Y586391I-8563J-33942D01* +G03X484548Y583852I34912J-2539D01* +G01X463102D01* +Y621088D01* +X463330Y623796D01* +X463331Y657741D01* +X463335Y657749D01* +X487864Y677151D01* +X487868Y677159D01* +X487870Y677167D01* +X488377Y719918D01* +X488372Y719925D01* +X385318Y817096D01* +X385315Y817104D01* +X385303Y824194D01* +G37* +G36* +X406659Y16289D02* +G02X410804Y22007I6016J0D01* +G03X434932Y57517I-10816J33301D01* +G02X440701Y63891I6005J363D01* +G03X473369Y90286I-1266J34979D01* +G01X552047D01* +G03X616683Y71637I35009J0D01* +G03X655114Y74001I17421J30352D01* +G02X663959Y71496I3372J-4963D01* +G02X664584Y68230I-12350J-4056D01* +G03X723434Y97474I34795J3815D01* +G02X723291Y101327I2253J2013D01* +G03X727206Y137973I-27637J21485D01* +G03X720330Y198773I-20361J28486D01* +G02X718054Y207321I2783J5318D01* +G03X722260Y235639I-29567J18863D01* +G02X723997Y239082I2916J689D01* +G03X745204Y271250I-13795J32168D01* +G01X823819D01* +X823504Y-5272D01* +X823494Y-5278D01* +X782134Y-6491D01* +X782127Y-6495D01* +X782120Y-6500D01* +X773702Y-17026D01* +X757092Y-28011D01* +X757086Y-28012D01* +X730310Y-29011D01* +X729024Y-29222D01* +X657530Y-31502D01* +X657524Y-31508D01* +X638646Y-56005D01* +X635661Y-58986D01* +X635655Y-58988D01* +X635649Y-58986D01* +X633148Y-56480D01* +G03X567043Y-61842I-32137J-13972D01* +G01X468402Y-62498D01* +X468395Y-62494D01* +X452164Y-43635D01* +G02X457683Y-33800I4551J3912D01* +G03X494638Y-16594I6467J34399D01* +G01X497259Y-15063D01* +X498361Y-15274D01* +G03X480803Y34434I12942J32526D01* +G01X478189Y32913D01* +X477083Y33126D01* +G03X429204Y2574I-12935J-32522D01* +G02X418370Y-629I-5991J339D01* +G01X409893Y10955D01* +G02X406659Y16289I2781J5334D01* +G37* +G36* +X410166Y490970D02* +G01X415847Y501324D01* +X463325Y546353D01* +X463328Y546360D01* +X463330Y546368D01* +X463268Y572858D01* +X463102Y574156D01* +Y583852D01* +X484548D01* +G03X551536Y569629I35004J0D01* +G02X553777Y571259I2689J-1341D01* +G02X556415Y570801I-514J-10787D01* +G03X599980Y604740I8563J33939D01* +G01X637390D01* +G03X699081Y588167I34563J5552D01* +G03X752948Y617657I18862J29489D01* +G01X824213D01* +X824099Y516753D01* +X754552D01* +G03X692723Y539240I-35004J0D01* +G02X688896Y538774I-2189J2033D01* +G03X634943Y512622I-19085J-29358D01* +G03X634801Y509466I34871J-3156D01* +G01X500872D01* +X497659Y514136D01* +X491369Y519731D01* +X483925Y523662D01* +X475758Y525702D01* +X471420Y525972D01* +X463063Y524960D01* +X455189Y521981D01* +X448254Y517209D01* +X442659Y510919D01* +X438728Y503475D01* +X436688Y495308D01* +X436418Y490970D01* +X410166D01* +G37* +G36* +X500872Y509466D02* +X634801D01* +G03X640085Y490970I35013J0D01* +G01X506422D01* +X505409Y499327D01* +X502431Y507201D01* +X500872Y509466D01* +G37* +G36* +X599537Y610292D02* +X636947D01* +G03X637390Y604740I35006J0D01* +G01X599980D01* +G03X599537Y610292I-35003J1D01* +G37* +G36* +X631179Y441200D02* +G01X668848D01* +X669860Y432843D01* +X671995Y427200D01* +X634101D01* +G03X631179Y441200I-35003J-1D01* +G37* +G36* +X631353Y441359D02* +G01X668689D01* +G02X668689Y441041I0J-159D01* +G01X631353D01* +G02X631353Y441359I0J159D01* +G37* +G36* +X739011D02* +G01X823854D01* +G02X823854Y441041I0J-159D01* +G01X739011D01* +G02X739011Y441359I0J159D01* +G37* +G36* +X753107Y617815D02* +G01X824055D01* +G02X824055Y617498I0J-159D01* +G01X753107D01* +G02X753107Y617815I0J159D01* +G37* +G36* +X599698Y610451D02* +G01X636789D01* +G02X636789Y610133I0J-159D01* +G01X599698D01* +G02X599698Y610451I0J159D01* +G37* +G36* +X754710Y516912D02* +G01X823940D01* +G02X823940Y516594I0J-159D01* +G01X754710D01* +G02X754710Y516912I0J159D01* +G37* +G36* +X501065Y509625D02* +G01X634642D01* +G02X634642Y509307I0J-159D01* +G01X501065D01* +G02X501065Y509625I0J159D01* +G37* +G36* +X346385Y234149D02* +G01X567469D01* +G02X567469Y233831I0J-159D01* +G01X346385D01* +G02X346385Y234149I0J159D01* +G37* +G36* +X637791D02* +G01X654275D01* +G02X654275Y233831I0J-159D01* +G01X637791D01* +G02X637791Y234149I0J159D01* +G37* +G36* +X634260Y427359D02* +G01X671825D01* +G02X671825Y427041I0J-159D01* +G01X634260D01* +G02X634260Y427359I0J159D01* +G37* +G36* +X350091Y377761D02* +G01X557551D01* +G02X557551Y377444I0J-159D01* +G01X350091D01* +G02X350091Y377761I0J159D01* +G37* +G36* +X745362Y271409D02* +G01X823660D01* +G02X823660Y271091I0J-159D01* +G01X745362D01* +G02X745362Y271409I0J159D01* +G37* +G36* +X473532Y90445D02* +G01X551888D01* +G02X551888Y90128I0J-159D01* +G01X473532D01* +G02X473532Y90445I0J159D01* +G37* +G36* +X600139Y604899D02* +G01X637229D01* +G02X637229Y604581I0J-159D01* +G01X600139D01* +G02X600139Y604899I0J159D01* +G37* +G36* +X463261Y584011D02* +G01X484389D01* +G02X484389Y583693I0J-159D01* +G01X463261D01* +G02X463261Y584011I0J159D01* +G37* +G36* +X410347Y491129D02* +G01X436259D01* +G02X436259Y490811I0J-159D01* +G01X410347D01* +G02X410347Y491129I0J159D01* +G37* +G36* +X506581D02* +G01X639898D01* +G02X639898Y490811I0J-159D01* +G01X506581D01* +G02X506581Y491129I0J159D01* +G37* +G36* +X481016Y299992D02* +G01X644182D01* +G02X644182Y299675I0J-159D01* +G01X481016D01* +G02X481016Y299992I0J159D01* +G37* +G36* +X341155Y316516D02* +G01X351830D01* +G02X351830Y316198I0J-159D01* +G01X341155D01* +G02X341155Y316516I0J159D01* +G37* +G36* +X-826956Y564701D02* +G02X-826956Y564701I27006J0D01* +G37* +G36* +X-826456Y-347199D02* +G02X-826456Y-347199I27006J0D01* +G37* +G36* +X-824606Y334651D02* +G02X-824606Y334651I27006J0D01* +G37* +G36* +X-728406Y624001D02* +G02X-728406Y624001I27006J0D01* +G37* +G36* +X-723996Y26431D02* +G02X-723996Y26431I27006J0D01* +G37* +G36* +X-610856Y-606399D02* +G02X-610856Y-606399I27006J0D01* +G37* +G36* +X-603026Y-400039D02* +G02X-603026Y-400039I27006J0D01* +G37* +G36* +X-556756Y702251D02* +G02X-556756Y702251I27006J0D01* +G37* +G36* +X-526306Y-185699D02* +G02X-526306Y-185699I27006J0D01* +G37* +G36* +X-523906Y240201D02* +G02X-523906Y240201I27006J0D01* +G37* +G36* +X-490846Y-597749D02* +G02X-490846Y-597749I27006J0D01* +G37* +G36* +X-452006Y790051D02* +G02X-452006Y790051I27006J0D01* +G37* +G36* +X-407206Y104851D02* +G02X-407206Y104851I27006J0D01* +G37* +G36* +X-390846Y-498049D02* +G02X-390846Y-498049I27006J0D01* +G37* +G36* +X-342006Y314291D02* +G02X-342006Y314291I27006J0D01* +G37* +G36* +X-326766Y645011D02* +G02X-326766Y645011I27006J0D01* +G37* +G36* +X-239406Y-210799D02* +G02X-239406Y-210799I27006J0D01* +G37* +G36* +X-211406Y83701D02* +G02X-211406Y83701I27006J0D01* +G37* +G36* +X-154406Y-499909D02* +G02X-154406Y-499909I27006J0D01* +G37* +G36* +X-126956Y500651D02* +G02X-126956Y500651I27006J0D01* +G37* +G36* +X-123456Y49501D02* +G02X-123456Y49501I27006J0D01* +G37* +G36* +X-70556Y-499589D02* +G02X-70556Y-499589I27006J0D01* +G37* +G36* +X-26116Y-40559D02* +G02X-26116Y-40559I27006J0D01* +G37* +G36* +X-316Y-505759D02* +G02X-316Y-505759I27006J0D01* +G37* +G36* +X39094Y205551D02* +G02X39094Y205551I27006J0D01* +G37* +G36* +X92304Y503211D02* +G02X92304Y503211I27006J0D01* +G37* +G36* +X147634Y-503009D02* +G02X147634Y-503009I27006J0D01* +G37* +G36* +X155924Y88401D02* +G02X155924Y88401I27006J0D01* +G37* +G36* +X264064Y-495769D02* +G02X264064Y-495769I27006J0D01* +G37* +G36* +X282994Y502411D02* +G02X282994Y502411I27006J0D01* +G37* +G36* +X352544Y-502999D02* +G02X352544Y-502999I27006J0D01* +G37* +G36* +X425894Y696551D02* +G02X425894Y696551I27006J0D01* +G37* +G36* +X439844Y798601D02* +G02X439844Y798601I27006J0D01* +G37* +G36* +X451194Y191301D02* +G02X451194Y191301I27006J0D01* +G37* +G36* +X467344Y258401D02* +G02X467344Y258401I27006J0D01* +G37* +G36* +X482164Y-321129D02* +G02X482164Y-321129I27006J0D01* +G37* +G36* +X547434Y-507049D02* +G02X547434Y-507049I27006J0D01* +G37* +G36* +X563194Y-289599D02* +G02X563194Y-289599I27006J0D01* +G37* +G36* +X572414Y-157639D02* +G02X572414Y-157639I27006J0D01* +G37* +G36* +X574644Y-3249D02* +G02X574644Y-3249I27006J0D01* +G37* +G36* +X759594Y780121D02* +G02X759594Y780121I27006J0D01* +G37* +G54D10* +X677798Y470923D02* +G01X695313Y479606D01* +X703897Y480661D02* +X719844Y477098D01* +X-819420Y699353D02* +X-819155Y665400D01* +X-630813Y820367D02* +X-606585Y820350D01* +X-803079Y-492580D02* +X-784575Y-491054D01* +X-421767Y-253926D02* +X-403901Y-258607D01* +X245726Y-3652D02* +X251127Y-20112D01* +X201196Y-61699D02* +X213953Y-63282D01* +X-411985Y261809D02* +X-396470Y261204D01* +X377123Y605950D02* +Y588652D01* +X347733Y313961D02* +X351770Y299450D01* +X496222Y-595050D02* +X494492Y-610810D01* +X-323360Y593580D02* +X-323241Y565226D01* +X10862Y506459D02* +X9901Y496176D01* +M02* diff --git a/gerbview/gerber_test_files/test_polygons_with_arcs_simple.gbr b/gerbview/gerber_test_files/test_polygons_with_arcs_simple.gbr new file mode 100644 index 0000000..7b03ab5 --- /dev/null +++ b/gerbview/gerber_test_files/test_polygons_with_arcs_simple.gbr @@ -0,0 +1,51 @@ +* +%FSLAX35Y35*% +%MOMM*% +%ADD10C,0.085000*% +%ADD11C,1.000000*% +%IPPOS*% +%LNl2p*% +%LPD*% +%SRX1Y1I0J0*% +G01* +G75* +G36* +X-824649Y824737D02* +X-824642Y824746D01* +X-824637Y824748D01* +X-600285Y824596D01* +G02X-596337Y813997I0J-6035D01* +G01X-596759Y813502D01* +X-599070Y812402D01* +X-599079Y812403D01* +X-600633Y812842D01* +G03X-591714Y760887I-18257J-29877D01* +G01X-589396Y761987D01* +X-587850Y761553D01* +G03X-543350Y814584I18275J29851D01* +G02X-538846Y824554I4504J3968D01* +G01X-387906Y824445D01* +X-387901Y824439D01* +X-387898Y718310D01* +X-387892Y718296D01* +X-387887Y718290D01* +X-337968Y678268D01* +X-337966Y678263D01* +X-337746Y625972D01* +G02X-347743Y621473I-6001J-23D01* +G03X-394478Y621365I-23307J-26119D01* +G02X-402955Y621809I-4016J4477D01* +G01X-407368Y626784D01* +X-409076Y628288D01* +G02X-406164Y638849I3817J4630D01* +G03X-421754Y706900I-5285J34600D01* +G01X-699601D01* +G03X-766967Y720229I-35002J0D01* +G02X-771614Y718929I-2844J1211D01* +G03X-817118Y687087I-10523J-33398D01* +G03X-817151Y685566I34972J-1522D01* +G01X-823562D01* +X-824649Y824737D01* +G37* + +M02* diff --git a/gerbview/gerbview.cpp b/gerbview/gerbview.cpp new file mode 100644 index 0000000..b128869 --- /dev/null +++ b/gerbview/gerbview.cpp @@ -0,0 +1,152 @@ +/** + * @file gerbview.cpp + * @brief GERBVIEW main file. + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <kiface_i.h> +#include <pgm_base.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <gestfich.h> + +#include <gerbview.h> +#include <gerbview_id.h> +#include <hotkeys.h> +#include <gerbview_frame.h> + +#include <build_version.h> + +#include <wx/file.h> +#include <wx/snglinst.h> + +// Colors for layers and items +COLORS_DESIGN_SETTINGS g_ColorsSettings; + + +const wxChar* g_GerberPageSizeList[] = { + wxT( "GERBER" ), // index 0: full size page selection, and do not show page limits + wxT( "GERBER" ), // index 1: full size page selection, and show page limits + wxT( "A4" ), + wxT( "A3" ), + wxT( "A2" ), + wxT( "A" ), + wxT( "B" ), + wxT( "C" ), +}; + + +namespace GERBV { + +static struct IFACE : public KIFACE_I +{ + // Of course all are virtual overloads, implementations of the KIFACE. + + IFACE( const char* aName, KIWAY::FACE_T aType ) : + KIFACE_I( aName, aType ) + {} + + bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ); + + void OnKifaceEnd(); + + wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) + { + switch( aClassId ) + { + case FRAME_GERBER: + { + GERBVIEW_FRAME* frame = new GERBVIEW_FRAME( aKiway, aParent ); + return frame; + } + break; + + default: + ; + } + + return NULL; + } + + /** + * Function IfaceOrAddress + * return a pointer to the requested object. The safest way to use this + * is to retrieve a pointer to a static instance of an interface, similar to + * how the KIFACE interface is exported. But if you know what you are doing + * use it to retrieve anything you want. + * + * @param aDataId identifies which object you want the address of. + * + * @return void* - and must be cast into the know type. + */ + void* IfaceOrAddress( int aDataId ) + { + return NULL; + } + +} kiface( "gerbview", KIWAY::FACE_GERBVIEW ); + +} // namespace + +using namespace GERBV; + +static PGM_BASE* process; + +KIFACE_I& Kiface() { return kiface; } + + +// KIFACE_GETTER's actual spelling is a substitution macro found in kiway.h. +// KIFACE_GETTER will not have name mangling due to declaration in kiway.h. +MY_API( KIFACE* ) KIFACE_GETTER( int* aKIFACEversion, int aKiwayVersion, PGM_BASE* aProgram ) +{ + process = (PGM_BASE*) aProgram; + return &kiface; +} + + +PGM_BASE& Pgm() +{ + wxASSERT( process ); // KIFACE_GETTER has already been called. + return *process; +} + + +bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) +{ + start_common( aCtlBits ); + + // Must be called before creating the main frame in order to + // display the real hotkeys in menus or tool tips + ReadHotkeyConfig( GERBVIEW_FRAME_NAME, GerbviewHokeysDescr ); + + return true; +} + + +void IFACE::OnKifaceEnd() +{ + end_common(); +} diff --git a/gerbview/gerbview.h b/gerbview/gerbview.h new file mode 100644 index 0000000..d54ec58 --- /dev/null +++ b/gerbview/gerbview.h @@ -0,0 +1,109 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GERBVIEW_H +#define GERBVIEW_H + +#include <vector> +#include <set> + + +#define CURSEUR_ON_GRILLE 0 +#define CURSEUR_OFF_GRILLE 1 + +/** +* size of single line of a text from a gerber file. +* warning: some files can have very long lines, so the buffer must be large. +*/ +#define GERBER_BUFZ 4000 + +/// List of page sizes +extern const wxChar* g_GerberPageSizeList[8]; + +// Type of photoplotter action: +#define GERB_ACTIVE_DRAW 1 // Activate light (lower pen) +#define GERB_STOP_DRAW 2 // Extinguish light (lift pen) +#define GERB_FLASH 3 // Flash + +// number fo draw layers in Gerbview +#define GERBER_DRAWLAYERS_COUNT 32 + +/** + * Enum GERBER_VISIBLE_ID + * is a set of visible GERBVIEW elements. + */ +enum GERBER_VISIBLE_ID +{ + DCODES_VISIBLE = 1, // visible item id cannot be 0 + // because this id is used as wxWidget id + GERBER_GRID_VISIBLE, + NEGATIVE_OBJECTS_VISIBLE, // use the selected color to draw negative objects + // instaed of background color, to make them visible + END_GERBER_VISIBLE_LIST // sentinel +}; + +// Interpolation type +enum Gerb_Interpolation +{ + GERB_INTERPOL_LINEAR_1X = 0, + GERB_INTERPOL_LINEAR_10X, + GERB_INTERPOL_LINEAR_01X, + GERB_INTERPOL_LINEAR_001X, + GERB_INTERPOL_ARC_NEG, + GERB_INTERPOL_ARC_POS +}; + + +// Command Type (GCodes) +enum Gerb_GCommand +{ + GC_MOVE = 0, + GC_LINEAR_INTERPOL_1X = 1, + GC_CIRCLE_NEG_INTERPOL = 2, + GC_CIRCLE_POS_INTERPOL = 3, + GC_COMMENT = 4, + GC_LINEAR_INTERPOL_10X = 10, + GC_LINEAR_INTERPOL_0P1X = 11, + GC_LINEAR_INTERPOL_0P01X = 12, + GC_TURN_ON_POLY_FILL = 36, + GC_TURN_OFF_POLY_FILL = 37, + GC_SELECT_TOOL = 54, + GC_PHOTO_MODE = 55, // can start a D03 flash command: redundant with D03 + GC_SPECIFY_INCHES = 70, + GC_SPECIFY_MILLIMETERS = 71, + GC_TURN_OFF_360_INTERPOL = 74, + GC_TURN_ON_360_INTERPOL = 75, + GC_SPECIFY_ABSOLUES_COORD = 90, + GC_SPECIFY_RELATIVEES_COORD = 91 +}; + + +enum Gerb_Analyse_Cmd +{ + CMD_IDLE = 0, + END_BLOCK, + ENTER_RS274X_CMD +}; + +#endif // ifndef GERBVIEW_H diff --git a/gerbview/gerbview.icns b/gerbview/gerbview.icns Binary files differnew file mode 100644 index 0000000..4ba9792 --- /dev/null +++ b/gerbview/gerbview.icns diff --git a/gerbview/gerbview.rc b/gerbview/gerbview.rc new file mode 100644 index 0000000..05e745b --- /dev/null +++ b/gerbview/gerbview.rc @@ -0,0 +1,3 @@ +icon_gerbview ICON "../bitmaps_png/icons/icon_gerbview.ico" + +#include "wx/msw/wx.rc" diff --git a/gerbview/gerbview_config.cpp b/gerbview/gerbview_config.cpp new file mode 100644 index 0000000..7bca894 --- /dev/null +++ b/gerbview/gerbview_config.cpp @@ -0,0 +1,148 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview_config.cpp + * @brief GerbView configuration. +*/ + +#include <fctsys.h> +#include <macros.h> +#include <id.h> +#include <common.h> +#include <class_drawpanel.h> +#include <gestfich.h> +#include <config_params.h> +#include <colors_selection.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <hotkeys.h> +#include <dialog_hotkeys_editor.h> + + +#define GROUP wxT("/gerbview") + + +void GERBVIEW_FRAME::Process_Config( wxCommandEvent& event ) +{ + int id = event.GetId(); + wxString FullFileName; + + switch( id ) + { + // Hotkey IDs + case ID_PREFERENCES_HOTKEY_EXPORT_CONFIG: + ExportHotkeyConfigToFile( GerbviewHokeysDescr, wxT( "gerbview" ) ); + break; + + case ID_PREFERENCES_HOTKEY_IMPORT_CONFIG: + ImportHotkeyConfigFromFile( GerbviewHokeysDescr, wxT( "gerbview" ) ); + break; + + case ID_PREFERENCES_HOTKEY_SHOW_EDITOR: + InstallHotkeyFrame( this, GerbviewHokeysDescr ); + break; + + case ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST: + + // Display current hotkey list for GerbView. + DisplayHotkeyList( this, GerbviewHokeysDescr ); + break; + + default: + wxMessageBox( wxT( "GERBVIEW_FRAME::Process_Config error" ) ); + break; + } +} + + +PARAM_CFG_ARRAY& GERBVIEW_FRAME::GetConfigurationSettings() +{ + if( !m_configSettings.empty() ) + return m_configSettings; + + m_configSettings.push_back( new PARAM_CFG_INT( true, wxT( "Units" ), + (int*) &g_UserUnit, 0, 0, 1 ) ); + + m_configSettings.push_back( new PARAM_CFG_INT( true, wxT( "DrawModeOption" ), + &m_displayMode, 2, 0, 2 ) ); + m_configSettings.push_back( new PARAM_CFG_SETCOLOR( true, + wxT( "DCodeColorEx" ), + &g_ColorsSettings.m_ItemsColors[ + DCODES_VISIBLE], + WHITE ) ); + m_configSettings.push_back( new PARAM_CFG_SETCOLOR( true, + wxT( "NegativeObjectsColorEx" ), + &g_ColorsSettings.m_ItemsColors[ + NEGATIVE_OBJECTS_VISIBLE], + DARKGRAY ) ); + m_configSettings.push_back( new PARAM_CFG_BOOL( true, + wxT( "DisplayPolarCoordinates" ), + &m_DisplayOptions.m_DisplayPolarCood, + false ) ); + + // Default colors for layers 0 to 31 + static const EDA_COLOR_T color_default[] = { + GREEN, BLUE, LIGHTGRAY, MAGENTA, + RED, DARKGREEN, BROWN, MAGENTA, + LIGHTGRAY, BLUE, GREEN, CYAN, + LIGHTRED, LIGHTMAGENTA, YELLOW, RED, + BLUE, BROWN, LIGHTCYAN, RED, + MAGENTA, CYAN, BROWN, MAGENTA, + LIGHTGRAY, BLUE, GREEN, DARKCYAN, + YELLOW, LIGHTMAGENTA, YELLOW, LIGHTGRAY, + }; + + // List of keywords used as identifiers in config. + // They *must* be static const and not temporarily created, + // because the parameter list that use these keywords does not store them, + // just points to them. + static const wxChar* keys[] = { + wxT("ColorLayer0Ex"), wxT("ColorLayer1Ex"), wxT("ColorLayer2Ex"), wxT("ColorLayer3Ex"), + wxT("ColorLayer4Ex"), wxT("ColorLayer5Ex"), wxT("ColorLayer6Ex"), wxT("ColorLayer7Ex"), + wxT("ColorLayer8Ex"), wxT("ColorLayer9Ex"), wxT("ColorLayer10Ex"), wxT("ColorLayer11Ex"), + wxT("ColorLayer12Ex"), wxT("ColorLayer13Ex"), wxT("ColorLayer14Ex"), wxT("ColorLayer15Ex"), + wxT("ColorLayer16Ex"), wxT("ColorLayer17Ex"), wxT("ColorLayer18Ex"), wxT("ColorLayer19Ex"), + wxT("ColorLayer20Ex"), wxT("ColorLayer21Ex"), wxT("ColorLayer22Ex"), wxT("ColorLayer23Ex"), + wxT("ColorLayer24Ex"), wxT("ColorLayer25Ex"), wxT("ColorLayer26Ex"), wxT("ColorLayer27Ex"), + wxT("ColorLayer28Ex"), wxT("ColorLayer29Ex"), wxT("ColorLayer30Ex"), wxT("ColorLayer31Ex"), + }; + + wxASSERT( DIM(keys) == DIM(color_default) ); + wxASSERT( DIM(keys) <= DIM(g_ColorsSettings.m_LayersColors) && DIM(keys) <= DIM(color_default) ); + + for( unsigned i = 0; i < DIM(keys); ++i ) + { + EDA_COLOR_T* prm = &g_ColorsSettings.m_LayersColors[i]; + + PARAM_CFG_SETCOLOR* prm_entry = + new PARAM_CFG_SETCOLOR( true, keys[i], prm, color_default[i] ); + + m_configSettings.push_back( prm_entry ); + } + + return m_configSettings; +} diff --git a/gerbview/gerbview_doc.icns b/gerbview/gerbview_doc.icns Binary files differnew file mode 100644 index 0000000..4b6de4a --- /dev/null +++ b/gerbview/gerbview_doc.icns diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp new file mode 100644 index 0000000..68ddadc --- /dev/null +++ b/gerbview/gerbview_frame.cpp @@ -0,0 +1,835 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview_frame.cpp + */ + +#include <fctsys.h> +#include <kiface_i.h> +#include <pgm_base.h> +#include <wxstruct.h> +#include <class_drawpanel.h> +#include <build_version.h> +#include <macros.h> +#include <trigo.h> +#include <base_units.h> +#include <colors_selection.h> +#include <class_gbr_layer_box_selector.h> +#include <msgpanel.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> +#include <pcbplot.h> +#include <gerbview_id.h> +#include <hotkeys.h> +#include <class_GERBER.h> +#include <dialog_helpers.h> +#include <class_DCodeSelectionbox.h> +#include <class_gerbview_layer_widget.h> +#include <class_gbr_screen.h> + + +// Config keywords +static const wxString cfgShowPageSizeOption( wxT( "PageSizeOpt" ) ); +static const wxString cfgShowDCodes( wxT( "ShowDCodesOpt" ) ); +static const wxString cfgShowNegativeObjects( wxT( "ShowNegativeObjectsOpt" ) ); +static const wxString cfgShowBorderAndTitleBlock( wxT( "ShowBorderAndTitleBlock" ) ); + + +GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ): + EDA_DRAW_FRAME( aKiway, aParent, FRAME_GERBER, wxT( "GerbView" ), + wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GERBVIEW_FRAME_NAME ) +{ + m_colorsSettings = &g_ColorsSettings; + m_gerberLayout = NULL; + m_zoomLevelCoeff = ZOOM_FACTOR( 110 ); // Adjusted to roughly displays zoom level = 1 + // when the screen shows a 1:1 image + // obviously depends on the monitor, + // but this is an acceptable value + + PAGE_INFO pageInfo( wxT( "GERBER" ) ); + SetPageSettings( pageInfo ); + + m_show_layer_manager_tools = true; + + m_showAxis = true; // true to show X and Y axis on screen + m_showBorderAndTitleBlock = false; // true for reference drawings. + m_hotkeysDescrList = GerbviewHokeysDescr; + m_SelLayerBox = NULL; + m_DCodeSelector = NULL; + m_displayMode = 0; + m_drillFileHistory.SetBaseId( ID_GERBVIEW_DRILL_FILE1 ); + + if( m_canvas ) + m_canvas->SetEnableBlockCommands( true ); + + // Give an icon + wxIcon icon; + icon.CopyFromBitmap( KiBitmap( icon_gerbview_xpm ) ); + SetIcon( icon ); + + SetLayout( new GBR_LAYOUT() ); + + SetVisibleLayers( -1 ); // All draw layers visible. + + SetScreen( new GBR_SCREEN( GetPageSettings().GetSizeIU() ) ); + + // Create the PCB_LAYER_WIDGET *after* SetLayout(): + wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); + int pointSize = font.GetPointSize(); + int screenHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ); + + if( screenHeight <= 900 ) + pointSize = (pointSize * 8) / 10; + + m_LayersManager = new GERBER_LAYER_WIDGET( this, m_canvas, pointSize ); + + // LoadSettings() *after* creating m_LayersManager, because LoadSettings() + // initialize parameters in m_LayersManager + LoadSettings( config() ); + + SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); + + if( m_LastGridSizeId < 0 ) + m_LastGridSizeId = 0; + if( m_LastGridSizeId > ID_POPUP_GRID_LEVEL_0_0_1MM-ID_POPUP_GRID_LEVEL_1000 ) + m_LastGridSizeId = ID_POPUP_GRID_LEVEL_0_0_1MM-ID_POPUP_GRID_LEVEL_1000; + GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); + + ReCreateMenuBar(); + ReCreateHToolbar(); + ReCreateOptToolbar(); + + m_auimgr.SetManagedWindow( this ); + + EDA_PANEINFO horiz; + horiz.HorizontalToolbarPane(); + + EDA_PANEINFO vert; + vert.VerticalToolbarPane(); + + EDA_PANEINFO mesg; + mesg.MessageToolbarPane(); + + // Create a wxAuiPaneInfo for the Layers Manager, not derived from the template. + // the Layers Manager is floatable, but initially docked at far right + EDA_PANEINFO lyrs; + lyrs.LayersToolbarPane(); + lyrs.MinSize( m_LayersManager->GetBestSize() ); + lyrs.BestSize( m_LayersManager->GetBestSize() ); + lyrs.Caption( _( "Visibles" ) ); + lyrs.TopDockable( false ).BottomDockable( false ); + + + if( m_mainToolBar ) + m_auimgr.AddPane( m_mainToolBar, + wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top().Row( 0 ) ); + + if( m_drawToolBar ) + m_auimgr.AddPane( m_drawToolBar, + wxAuiPaneInfo( vert ).Name( wxT( "m_drawToolBar" ) ).Right().Row( 1 ) ); + + m_auimgr.AddPane( m_LayersManager, + lyrs.Name( wxT( "m_LayersManagerToolBar" ) ).Right().Layer( 0 ) ); + + if( m_optionsToolBar ) + m_auimgr.AddPane( m_optionsToolBar, + wxAuiPaneInfo( vert ).Name( wxT( "m_optionsToolBar" ) ).Left() ); + + if( m_canvas ) + m_auimgr.AddPane( m_canvas, + wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); + + if( m_messagePanel ) + m_auimgr.AddPane( m_messagePanel, + wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer( 10 ) ); + + ReFillLayerWidget(); // this is near end because contents establish size + m_LayersManager->ReFillRender(); // Update colors in Render after the config is read + m_auimgr.Update(); + + setActiveLayer( 0, true ); + Zoom_Automatique( false ); // Gives a default zoom value +} + + +GERBVIEW_FRAME::~GERBVIEW_FRAME() +{ +} + + +void GERBVIEW_FRAME::OnCloseWindow( wxCloseEvent& Event ) +{ + Destroy(); +} + + +bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ) +{ + // The current project path is also a valid command parameter. Check if a single path + // rather than a file name was passed to GerbView and use it as the initial MRU path. + if( aFileSet.size() > 0 ) + { + wxString path = aFileSet[0]; + + // For some reason wxApp appears to leave the trailing double quote on quoted + // parameters which are required for paths with spaces. Maybe this should be + // pushed back into PGM_SINGLE_TOP::OnPgmInit() but that may cause other issues. + // We can't buy a break! + if( path.Last() == wxChar( '\"' ) ) + path.RemoveLast(); + + if( !wxFileExists( path ) && wxDirExists( path ) ) + { + wxLogDebug( wxT( "MRU path: %s." ), GetChars( path ) ); + m_mruPath = path; + return true; + } + + const unsigned limit = std::min( unsigned( aFileSet.size() ), + unsigned( GERBER_DRAWLAYERS_COUNT ) ); + + int layer = 0; + + for( unsigned i=0; i<limit; ++i, ++layer ) + { + setActiveLayer( layer ); + LoadGerberFiles( aFileSet[i] ); + } + } + + Zoom_Automatique( true ); // Zoom fit in frame + + UpdateTitleAndInfo(); + + return true; +} + + +double GERBVIEW_FRAME::BestZoom() +{ + GERBER_DRAW_ITEM* item = GetGerberLayout()->m_Drawings; + + // gives a minimal value to zoom, if no item in list + if( item == NULL ) + return ZOOM_FACTOR( 350.0 ); + + EDA_RECT bbox = GetGerberLayout()->ComputeBoundingBox(); + + wxSize size = m_canvas->GetClientSize(); + + double x = (double) bbox.GetWidth() / (double) size.x; + double y = (double) bbox.GetHeight() / (double) size.y; + SetScrollCenterPosition( bbox.Centre() ); + + double best_zoom = std::max( x, y ); + return best_zoom; +} + + +void GERBVIEW_FRAME::LoadSettings( wxConfigBase* aCfg ) +{ + EDA_DRAW_FRAME::LoadSettings( aCfg ); + + // was: wxGetApp().ReadCurrentSetupValues( GetConfigurationSettings() ); + wxConfigLoadSetups( aCfg, GetConfigurationSettings() ); + + PAGE_INFO pageInfo( wxT( "GERBER" ) ); + + aCfg->Read( cfgShowBorderAndTitleBlock, &m_showBorderAndTitleBlock, false ); + + if( m_showBorderAndTitleBlock ) + { + wxString pageType; + + aCfg->Read( cfgShowPageSizeOption, &pageType, wxT( "GERBER" ) ); + + pageInfo.SetType( pageType ); + } + + SetPageSettings( pageInfo ); + + GetScreen()->InitDataPoints( pageInfo.GetSizeIU() ); + + bool tmp; + aCfg->Read( cfgShowDCodes, &tmp, true ); + SetElementVisibility( DCODES_VISIBLE, tmp ); + aCfg->Read( cfgShowNegativeObjects, &tmp, false ); + SetElementVisibility( NEGATIVE_OBJECTS_VISIBLE, tmp ); + + // because we have 2 file histories, we must read this one + // using a specific path + aCfg->SetPath( wxT( "drl_files" ) ); + m_drillFileHistory.Load( *aCfg ); + aCfg->SetPath( wxT( ".." ) ); +} + + +void GERBVIEW_FRAME::SaveSettings( wxConfigBase* aCfg ) +{ + EDA_DRAW_FRAME::SaveSettings( aCfg ); + + // was: wxGetApp().SaveCurrentSetupValues( GetConfigurationSettings() ); + wxConfigSaveSetups( aCfg, GetConfigurationSettings() ); + + aCfg->Write( cfgShowPageSizeOption, GetPageSettings().GetType() ); + aCfg->Write( cfgShowBorderAndTitleBlock, m_showBorderAndTitleBlock ); + aCfg->Write( cfgShowDCodes, IsElementVisible( DCODES_VISIBLE ) ); + aCfg->Write( cfgShowNegativeObjects, + IsElementVisible( NEGATIVE_OBJECTS_VISIBLE ) ); + + // Save the drill file history list. + // Because we have 2 file histories, we must save this one + // in a specific path + aCfg->SetPath( wxT( "drl_files" ) ); + m_drillFileHistory.Save( *aCfg ); + aCfg->SetPath( wxT( ".." ) ); +} + + +void GERBVIEW_FRAME::ReFillLayerWidget() +{ + m_LayersManager->ReFill(); + + wxAuiPaneInfo& lyrs = m_auimgr.GetPane( m_LayersManager ); + + wxSize bestz = m_LayersManager->GetBestSize(); + + lyrs.MinSize( bestz ); + lyrs.BestSize( bestz ); + lyrs.FloatingSize( bestz ); + + if( lyrs.IsDocked() ) + m_auimgr.Update(); + else + m_LayersManager->SetSize( bestz ); + + syncLayerWidget(); +} + + +void GERBVIEW_FRAME::SetElementVisibility( GERBER_VISIBLE_ID aItemIdVisible, + bool aNewState ) +{ + switch( aItemIdVisible ) + { + case DCODES_VISIBLE: + m_DisplayOptions.m_DisplayDCodes = aNewState; + break; + + case NEGATIVE_OBJECTS_VISIBLE: + m_DisplayOptions.m_DisplayNegativeObjects = aNewState; + break; + + case GERBER_GRID_VISIBLE: + SetGridVisibility( aNewState ); + break; + + default: + wxLogDebug( wxT( "GERBVIEW_FRAME::SetElementVisibility(): bad arg %d" ), aItemIdVisible ); + } + + m_LayersManager->SetRenderState( aItemIdVisible, aNewState ); +} + + +int GERBVIEW_FRAME::getNextAvailableLayer( int aLayer ) const +{ + int layer = aLayer; + + for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; ++i ) + { + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); + + if( gerber == NULL || gerber->m_FileName.IsEmpty() ) + return layer; + + ++layer; + + if( layer >= GERBER_DRAWLAYERS_COUNT ) + layer = 0; + } + + return NO_AVAILABLE_LAYERS; +} + + +void GERBVIEW_FRAME::syncLayerWidget() +{ + m_LayersManager->SelectLayer( getActiveLayer() ); + UpdateTitleAndInfo(); +} + + +void GERBVIEW_FRAME::syncLayerBox() +{ + m_SelLayerBox->Resync(); + m_SelLayerBox->SetSelection( getActiveLayer() ); + + int dcodeSelected = -1; + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() ); + + if( gerber ) + dcodeSelected = gerber->m_Selected_Tool; + + if( m_DCodeSelector ) + { + m_DCodeSelector->SetDCodeSelection( dcodeSelected ); + m_DCodeSelector->Enable( gerber != NULL ); + } + + UpdateTitleAndInfo(); +} + + +void GERBVIEW_FRAME::Liste_D_Codes() +{ + int ii, jj; + D_CODE* pt_D_code; + wxString Line; + wxArrayString list; + double scale = g_UserUnit == INCHES ? IU_PER_MILS * 1000 : + IU_PER_MM; + int curr_layer = getActiveLayer(); + + for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer ) + { + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); + + if( gerber == NULL ) + continue; + + if( gerber->UsedDcodeNumber() == 0 ) + continue; + + if( layer == curr_layer ) + Line.Printf( wxT( "*** Active layer (%2.2d) ***" ), layer + 1 ); + else + Line.Printf( wxT( "*** layer %2.2d ***" ), layer + 1 ); + + list.Add( Line ); + + const char* units = g_UserUnit == INCHES ? "\"" : "mm"; + for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ ) + { + pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE, false ); + + if( pt_D_code == NULL ) + continue; + + if( !pt_D_code->m_InUse && !pt_D_code->m_Defined ) + continue; + + Line.Printf( wxT( "tool %2.2d: D%2.2d V %.4f %s H %.4f %s %s " ), + jj, + pt_D_code->m_Num_Dcode, + pt_D_code->m_Size.y / scale, units, + pt_D_code->m_Size.x / scale, units, + D_CODE::ShowApertureType( pt_D_code->m_Shape ) + ); + + if( !pt_D_code->m_Defined ) + Line += wxT( "(not used)" ); + + if( !pt_D_code->m_InUse ) + Line += wxT( "(in use)" ); + + list.Add( Line ); + jj++; + } + } + + wxSingleChoiceDialog dlg( this, wxEmptyString, _( "D Codes" ), list, (void**) NULL, + wxCHOICEDLG_STYLE & ~wxCANCEL ); + + dlg.ShowModal(); +} + + + +void GERBVIEW_FRAME::UpdateTitleAndInfo() +{ + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() ); + wxString text; + + // Display the gerber filename + if( gerber == NULL ) + { + text.Printf( wxT( "GerbView %s" ), GetChars( GetBuildVersion() ) ); + SetTitle( text ); + SetStatusText( wxEmptyString, 0 ); + text.Printf( _( "Layer %d not in use" ), getActiveLayer() + 1 ); + m_TextInfo->SetValue( text ); + ClearMsgPanel(); + return; + } + + text = _( "File:" ); + text << wxT( " " ) << gerber->m_FileName; + + if( gerber->m_IsX2_file ) + text << wxT( " " ) << _( "(with X2 Attributes)" ); + + SetTitle( text ); + + gerber->DisplayImageInfo(); + + // Display Image Name and Layer Name (from the current gerber data): + text.Printf( _( "Image name: '%s' Layer name: '%s'" ), + GetChars( gerber->m_ImageName ), + GetChars( gerber->GetLayerParams().m_LayerName ) ); + SetStatusText( text, 0 ); + + // Display data format like fmt in X3.4Y3.4 no LZ or fmt mm X2.3 Y3.5 no TZ in main toolbar + text.Printf( wxT( "fmt: %s X%d.%d Y%d.%d no %cZ" ), + gerber->m_GerbMetric ? wxT( "mm" ) : wxT( "in" ), + gerber->m_FmtLen.x - gerber->m_FmtScale.x, gerber->m_FmtScale.x, + gerber->m_FmtLen.y - gerber->m_FmtScale.y, gerber->m_FmtScale.y, + gerber->m_NoTrailingZeros ? 'T' : 'L' ); + + if( gerber->m_IsX2_file ) + text << wxT(" ") << _( "X2 attr" ); + + m_TextInfo->SetValue( text ); + + if( EnsureTextCtrlWidth( m_TextInfo, &text ) ) // Resized + m_auimgr.Update(); +} + + +bool GERBVIEW_FRAME::IsElementVisible( GERBER_VISIBLE_ID aItemIdVisible ) const +{ + switch( aItemIdVisible ) + { + case DCODES_VISIBLE: + return m_DisplayOptions.m_DisplayDCodes; + break; + + case NEGATIVE_OBJECTS_VISIBLE: + return m_DisplayOptions.m_DisplayNegativeObjects; + break; + + case GERBER_GRID_VISIBLE: + return IsGridVisible(); + break; + + default: + wxLogDebug( wxT( "GERBVIEW_FRAME::IsElementVisible(): bad arg %d" ), aItemIdVisible ); + } + + return true; +} + + +long GERBVIEW_FRAME::GetVisibleLayers() const +{ + return -1; // TODO +} + + +void GERBVIEW_FRAME::SetVisibleLayers( long aLayerMask ) +{ +// GetGerberLayout()->SetVisibleLayers( aLayerMask ); +} + + +bool GERBVIEW_FRAME::IsLayerVisible( int aLayer ) const +{ + if( ! m_DisplayOptions.m_IsPrinting ) + return m_LayersManager->IsLayerVisible( aLayer ); + else + return GetGerberLayout()->IsLayerPrintable( aLayer ); +} + + +EDA_COLOR_T GERBVIEW_FRAME::GetVisibleElementColor( GERBER_VISIBLE_ID aItemIdVisible ) const +{ + EDA_COLOR_T color = UNSPECIFIED_COLOR; + + switch( aItemIdVisible ) + { + case NEGATIVE_OBJECTS_VISIBLE: + case DCODES_VISIBLE: + color = m_colorsSettings->GetItemColor( aItemIdVisible ); + break; + + case GERBER_GRID_VISIBLE: + color = GetGridColor(); + break; + + default: + wxLogDebug( wxT( "GERBVIEW_FRAME::GetVisibleElementColor(): bad arg %d" ), + (int)aItemIdVisible ); + } + + return color; +} + + +void GERBVIEW_FRAME::SetGridVisibility( bool aVisible ) +{ + EDA_DRAW_FRAME::SetGridVisibility( aVisible ); + m_LayersManager->SetRenderState( GERBER_GRID_VISIBLE, aVisible ); +} + + +void GERBVIEW_FRAME::SetVisibleElementColor( GERBER_VISIBLE_ID aItemIdVisible, + EDA_COLOR_T aColor ) +{ + switch( aItemIdVisible ) + { + case NEGATIVE_OBJECTS_VISIBLE: + case DCODES_VISIBLE: + m_colorsSettings->SetItemColor( aItemIdVisible, aColor ); + break; + + case GERBER_GRID_VISIBLE: + SetGridColor( aColor ); + m_colorsSettings->SetItemColor( aItemIdVisible, aColor ); + break; + + default: + wxLogDebug( wxT( "GERBVIEW_FRAME::SetVisibleElementColor(): bad arg %d" ), + (int) aItemIdVisible ); + } +} + +EDA_COLOR_T GERBVIEW_FRAME::GetNegativeItemsColor() const +{ + if( IsElementVisible( NEGATIVE_OBJECTS_VISIBLE ) ) + return GetVisibleElementColor( NEGATIVE_OBJECTS_VISIBLE ); + else + return GetDrawBgColor(); +} + + +EDA_COLOR_T GERBVIEW_FRAME::GetLayerColor( int aLayer ) const +{ + return m_colorsSettings->GetLayerColor( aLayer ); +} + + +void GERBVIEW_FRAME::SetLayerColor( int aLayer, EDA_COLOR_T aColor ) +{ + m_colorsSettings->SetLayerColor( aLayer, aColor ); +} + + +int GERBVIEW_FRAME::getActiveLayer() +{ + return ( (GBR_SCREEN*) GetScreen() )->m_Active_Layer; +} + + +void GERBVIEW_FRAME::setActiveLayer( int aLayer, bool doLayerWidgetUpdate ) +{ + ( (GBR_SCREEN*) GetScreen() )->m_Active_Layer = aLayer; + + if( doLayerWidgetUpdate ) + m_LayersManager->SelectLayer( getActiveLayer() ); +} + + +void GERBVIEW_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings ) +{ + m_paper = aPageSettings; + + if( GetScreen() ) + GetScreen()->InitDataPoints( aPageSettings.GetSizeIU() ); +} + + +const PAGE_INFO& GERBVIEW_FRAME::GetPageSettings() const +{ + return m_paper; +} + + +const wxSize GERBVIEW_FRAME::GetPageSizeIU() const +{ + // this function is only needed because EDA_DRAW_FRAME is not compiled + // with either -DPCBNEW or -DEESCHEMA, so the virtual is used to route + // into an application specific source file. + return GetPageSettings().GetSizeIU(); +} + + +const TITLE_BLOCK& GERBVIEW_FRAME::GetTitleBlock() const +{ + wxASSERT( m_gerberLayout ); + return m_gerberLayout->GetTitleBlock(); +} + + +void GERBVIEW_FRAME::SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) +{ + wxASSERT( m_gerberLayout ); + m_gerberLayout->SetTitleBlock( aTitleBlock ); +} + + +const wxPoint& GERBVIEW_FRAME::GetAuxOrigin() const +{ + wxASSERT( m_gerberLayout ); + return m_gerberLayout->GetAuxOrigin(); +} + + +void GERBVIEW_FRAME::SetAuxOrigin( const wxPoint& aPosition ) +{ + wxASSERT( m_gerberLayout ); + m_gerberLayout->SetAuxOrigin( aPosition ); +} + + +void GERBVIEW_FRAME::SetCurItem( GERBER_DRAW_ITEM* aItem, bool aDisplayInfo ) +{ + GetScreen()->SetCurItem( aItem ); + + if( aItem ) + { + if( aDisplayInfo ) + { + MSG_PANEL_ITEMS items; + aItem->GetMsgPanelInfo( items ); + SetMsgPanel( items ); + } + } + else + { + EraseMsgBox(); + } +} + + +EDA_RECT GERBVIEW_FRAME::GetGerberLayoutBoundingBox() +{ + GetGerberLayout()->ComputeBoundingBox(); + return GetGerberLayout()->GetBoundingBox(); +} + +void GERBVIEW_FRAME::UpdateStatusBar() +{ + EDA_DRAW_FRAME::UpdateStatusBar(); + + GBR_SCREEN* screen = (GBR_SCREEN*) GetScreen(); + + if( !screen ) + return; + + int dx; + int dy; + double dXpos; + double dYpos; + wxString line; + wxString locformatter; + + if( m_DisplayOptions.m_DisplayPolarCood ) // display relative polar coordinates + { + double theta, ro; + + dx = GetCrossHairPosition().x - screen->m_O_Curseur.x; + dy = GetCrossHairPosition().y - screen->m_O_Curseur.y; + + // atan2 in the 0,0 case returns 0 + theta = RAD2DEG( atan2( -dy, dx ) ); + + ro = hypot( dx, dy ); + wxString formatter; + switch( g_UserUnit ) + { + case INCHES: + formatter = wxT( "Ro %.6f Th %.1f" ); + break; + + case MILLIMETRES: + formatter = wxT( "Ro %.5f Th %.1f" ); + break; + + case UNSCALED_UNITS: + formatter = wxT( "Ro %f Th %f" ); + break; + + case DEGREES: + wxASSERT( false ); + break; + } + + line.Printf( formatter, To_User_Unit( g_UserUnit, ro ), theta ); + + SetStatusText( line, 3 ); + } + + // Display absolute coordinates: + dXpos = To_User_Unit( g_UserUnit, GetCrossHairPosition().x ); + dYpos = To_User_Unit( g_UserUnit, GetCrossHairPosition().y ); + + wxString absformatter; + + switch( g_UserUnit ) + { + case INCHES: + absformatter = wxT( "X %.6f Y %.6f" ); + locformatter = wxT( "dx %.6f dy %.6f dist %.4f" ); + break; + + case MILLIMETRES: + absformatter = wxT( "X %.5f Y %.5f" ); + locformatter = wxT( "dx %.5f dy %.5f dist %.3f" ); + break; + + case UNSCALED_UNITS: + absformatter = wxT( "X %f Y %f" ); + locformatter = wxT( "dx %f dy %f dist %f" ); + break; + + case DEGREES: + wxASSERT( false ); + break; + } + + line.Printf( absformatter, dXpos, dYpos ); + SetStatusText( line, 2 ); + + if( !m_DisplayOptions.m_DisplayPolarCood ) // display relative cartesian coordinates + { + // Display relative coordinates: + dx = GetCrossHairPosition().x - screen->m_O_Curseur.x; + dy = GetCrossHairPosition().y - screen->m_O_Curseur.y; + dXpos = To_User_Unit( g_UserUnit, dx ); + dYpos = To_User_Unit( g_UserUnit, dy ); + + // We already decided the formatter above + line.Printf( locformatter, dXpos, dYpos, hypot( dXpos, dYpos ) ); + SetStatusText( line, 3 ); + } +} + + +const wxString GERBVIEW_FRAME::GetZoomLevelIndicator() const +{ + return EDA_DRAW_FRAME::GetZoomLevelIndicator(); +} diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h new file mode 100644 index 0000000..383ab54 --- /dev/null +++ b/gerbview/gerbview_frame.h @@ -0,0 +1,694 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview_frame.h + */ + +#ifndef WX_GERBER_STRUCT_H +#define WX_GERBER_STRUCT_H + + +#include <config_params.h> +#include <draw_frame.h> + +#include <gerbview.h> +#include <class_gbr_layout.h> +#include <class_gbr_screen.h> +#include <class_page_info.h> + +#define NO_AVAILABLE_LAYERS UNDEFINED_LAYER + +class DCODE_SELECTION_BOX; +class GERBER_LAYER_WIDGET; +class GBR_LAYER_BOX_SELECTOR; +class GERBER_DRAW_ITEM; + + +/** + * Class GBR_DISPLAY_OPTIONS + * A helper class to handle display options. + */ +class GBR_DISPLAY_OPTIONS +{ +public: + bool m_DisplayFlashedItemsFill; + bool m_DisplayLinesFill; + bool m_DisplayPolygonsFill; + bool m_DisplayPolarCood; + bool m_DisplayDCodes; + bool m_DisplayNegativeObjects; + bool m_IsPrinting; + +public: + GBR_DISPLAY_OPTIONS() + { + m_DisplayFlashedItemsFill = true; + m_DisplayLinesFill = true; + m_DisplayPolygonsFill = true; + m_DisplayPolarCood = false; + m_DisplayDCodes = true; + m_IsPrinting = false; + m_DisplayNegativeObjects = false; + } +}; + + +/** + * Class GERBVIEW_FRAME + * is the main window used in GerbView. + */ + +#define GERBVIEW_FRAME_NAME wxT( "GerberFrame" ) + +class GERBVIEW_FRAME : public EDA_DRAW_FRAME // PCB_BASE_FRAME +{ + GBR_LAYOUT* m_gerberLayout; + wxPoint m_grid_origin; + PAGE_INFO m_paper; // used only to show paper limits to screen + +public: + GBR_DISPLAY_OPTIONS m_DisplayOptions; + + /** + * Function SetLayout + * sets the m_gerberLayout member in such as way as to ensure deleting any previous + * GBR_LAYOUT. + * @param aLayout The GBR_LAYOUT to put into the frame. + */ + void SetLayout( GBR_LAYOUT* aLayout ) + { + delete m_gerberLayout; + m_gerberLayout = aLayout; + } + + GBR_LAYOUT* GetGerberLayout() const + { + wxASSERT( m_gerberLayout ); + return m_gerberLayout; + } + + /** + * Function GetItemsList + * @return the first GERBER_DRAW_ITEM * item of the items list + */ + GERBER_DRAW_ITEM* GetItemsList() + { + GERBER_DRAW_ITEM* item = GetGerberLayout()->m_Drawings; + + return (GERBER_DRAW_ITEM*) item; + } + + /** + * Function GetGerberLayoutBoundingBox + * calculates the bounding box containing all gerber items. + * @return EDA_RECT - the items bounding box + */ + EDA_RECT GetGerberLayoutBoundingBox(); + + void SetPageSettings( const PAGE_INFO& aPageSettings ); // overload + const PAGE_INFO& GetPageSettings() const; // overload + const wxSize GetPageSizeIU() const; // overload + + const wxPoint& GetAuxOrigin() const; // overload + void SetAuxOrigin( const wxPoint& aPoint ); // overload + + const wxPoint& GetGridOrigin() const { return m_grid_origin; } // overload + void SetGridOrigin( const wxPoint& aPoint ) // overload + { + m_grid_origin = aPoint; + } + + const TITLE_BLOCK& GetTitleBlock() const; // overload + void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ); // overload + + /** + * Function SetCurItem + * sets the currently selected item and displays it in the MsgPanel. + * If the given item is NULL then the MsgPanel is erased and there is no + * currently selected item. This function is intended to make the process + * of "selecting" an item more formal, and to indivisibly tie the operation + * of selecting an item to displaying it using GERBER_DRAW_ITEM::Display_Infos(). + * @param aItem The GERBER_DRAW_ITEM to make the selected item or NULL if none. + * @param aDisplayInfo = true to display item info, false if not (default = true) + */ + void SetCurItem( GERBER_DRAW_ITEM* aItem, bool aDisplayInfo = true ); + + /** Install the dialog box for layer selection + * @param aDefaultLayer = Preselection (NB_PCB_LAYERS for "(Deselect)" layer) + * @param aCopperLayerCount = number of copper layers + * @param aShowDeselectOption = display a "(Deselect)" radiobutton (when set to true) + * @return new layer value (NB_PCB_LAYERS when "(Deselect)" radiobutton selected), + * or -1 if canceled + * + * Providing the option to also display a "(Deselect)" radiobutton makes the + * GerbView's "Export to Pcbnew" command) more "user friendly", + * by permitting any layer to be "deselected" immediately after its + * corresponding radiobutton has been clicked on. (It would otherwise be + * necessary to first cancel the "Select Layer:" dialog box (invoked after a + * different radiobutton is clicked on) prior to then clicking on the "Deselect" + * button provided within the "Layer selection:" dialog box). + */ + int SelectPCBLayer( int aDefaultLayer, int aOpperLayerCount, bool aNullLayer = false ); + +protected: + GERBER_LAYER_WIDGET* m_LayersManager; + + // Auxiliary file history used to store drill files history. + wxFileHistory m_drillFileHistory; + /// The last filename chosen to be proposed to the user + wxString m_lastFileName; +public: + GBR_LAYER_BOX_SELECTOR* m_SelLayerBox; + DCODE_SELECTION_BOX* m_DCodeSelector; // a list box to select the dcode Id to highlight. + wxTextCtrl* m_TextInfo; // a wxTextCtrl used to display some info about + // gerber data (format..) + wxArrayString m_DCodesList; // an array string containing all decodes Id (10 to 999) +private: + // list of PARAM_CFG_xxx to read/write parameters saved in config + PARAM_CFG_ARRAY m_configSettings; + COLORS_DESIGN_SETTINGS* m_colorsSettings; + + int m_displayMode; // Gerber images ("layers" in Gerbview) can be drawn: + // - in fast mode (write mode) but if there are negative + // items only the last image is correctly drawn (no + // problem to see only one image or when no negative items) + // - in "exact" mode (but slower) in write mode: + // last image covers previous images + // - in "exact" mode (also slower) in OR mode + // (transparency mode) + // m_displayMode = 0, 1 or 2 + + bool m_show_layer_manager_tools; + + // An array sting to store warning messages when reaging a gerber file. + wxArrayString m_Messages; + +public: + GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ); + ~GERBVIEW_FRAME(); + + void OnCloseWindow( wxCloseEvent& Event ); + + bool OpenProjectFiles( const std::vector<wxString>& aFileSet, int aCtl ); // overload KIWAY_PLAYER + + // Virtual basic functions: + void RedrawActiveWindow( wxDC* DC, bool EraseBg ); + void ReCreateHToolbar(); + + /** + * Function ReCreateVToolbar + * creates or updates the right vertical toolbar. + * + * @note This is currently not used. + */ + void ReCreateVToolbar(); + + /** + * Create or update the left vertical toolbar (option toolbar + */ + void ReCreateOptToolbar(); + + void ReCreateMenuBar(); + void OnLeftClick( wxDC* DC, const wxPoint& MousePos ); + void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ); + bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); + double BestZoom(); + void UpdateStatusBar(); + + /** + * Function GetZoomLevelIndicator + * returns a human readable value which can be displayed as zoom + * level indicator in dialogs. + * Virtual from the base class + */ + const wxString GetZoomLevelIndicator() const; + + /** + * Function ReportMessage + * Add a message (a string) in message list + * for instance when reading a Gerber file + * @param aMessage = the string to add in list + */ + void ReportMessage( const wxString aMessage ) + { + m_Messages.Add( aMessage ); + } + + /** + * Function ClearMessageList + * Clear the message list + * Call it before reading a Gerber file + */ + void ClearMessageList() + { + m_Messages.Clear(); + } + + /** + * Function GetDisplayMode + * @return 0 for fast mode (not fully compatible with negative objects) + * 1 for exact mode, write mode + * 2 for exact mode, OR mode (transparency mode) + */ + int GetDisplayMode() { return m_displayMode; } + + /** + * Function SetDisplayMode + * @param aMode = 0 for fast mode + * 1 for exact mode, write mode + * 2 for exact mode, OR mode (transparency mode) + */ + void SetDisplayMode( int aMode ) { m_displayMode = aMode; } + + /** + * Function IsElementVisible + * tests whether a given element category is visible. Keep this as an + * inline function. + * @param aItemIdVisible is an item id from the enum GERBER_VISIBLE_ID + * @return bool - true if the element is visible. + */ + bool IsElementVisible( GERBER_VISIBLE_ID aItemIdVisible ) const; + + /** + * Function SetElementVisibility + * changes the visibility of an element category + * @param aItemIdVisible is an item id from the enum GERBER_VISIBLE_ID + * @param aNewState = The new visibility state of the element category + * (see enum PCB_VISIBLE) + */ + void SetElementVisibility( GERBER_VISIBLE_ID aItemIdVisible, bool aNewState ); + + /** + * Function SetGridVisibility(), virtual from EDA_DRAW_FRAME + * It may be overloaded by derived classes + * @param aVisible = true if the grid must be shown + */ + void SetGridVisibility( bool aVisible ); + + /** + * Function GetVisibleLayers + * is a proxy function that calls the correspondent function in m_BoardSettings + * Returns a bit-mask of all the layers that are visible + * @return long - the visible layers in bit-mapped form. + */ + long GetVisibleLayers() const; + + /** + * Function SetVisibleLayers + * is a proxy function that calls the correspondent function in m_BoardSettings + * changes the bit-mask of visible layers + * @param aLayerMask = The new bit-mask of visible layers + */ + void SetVisibleLayers( long aLayerMask ); + + /** + * Function IsLayerVisible + * tests whether a given layer is visible + * @param aLayer = The layer to be tested + * @return bool - true if the layer is visible. + */ + bool IsLayerVisible( int aLayer ) const; + + /** + * Function GetVisibleElementColor + * returns the color of a gerber visible element. + */ + EDA_COLOR_T GetVisibleElementColor( GERBER_VISIBLE_ID aItemIdVisible ) const; + + void SetVisibleElementColor( GERBER_VISIBLE_ID aItemIdVisible, EDA_COLOR_T aColor ); + + /** + * Function GetLayerColor + * gets a layer color for any valid layer. + */ + EDA_COLOR_T GetLayerColor( int aLayer ) const; + + /** + * Function SetLayerColor + * changes a layer color for any valid layer. + */ + void SetLayerColor( int aLayer, EDA_COLOR_T aColor ); + + /** + * Function GetNegativeItemsColor + * @return the color of negative items. + * This is usually the background color, but can be an other color + * in order to see negative objects + */ + EDA_COLOR_T GetNegativeItemsColor() const; + + /** + * Function DisplayLinesSolidMode + * @return true to draw gerber lines in solid (filled) mode, + * false to draw gerber lines in sketch mode + */ + bool DisplayLinesSolidMode() + { + return m_DisplayOptions.m_DisplayLinesFill; + } + + /** + * Function DisplayPolygonsSolidMode + * @return true to draw polygon in solid (filled) mode, + * false to draw polygon outlines only + */ + bool DisplayPolygonsSolidMode() + { + return m_DisplayOptions.m_DisplayPolygonsFill; + } + + /** + * Function DisplayFlashedItemsSolidMode + * @return true to draw flashed items in solid (filled) mode, + * false to draw draw flashed in sketch mode + */ + bool DisplayFlashedItemsSolidMode() + { + return m_DisplayOptions.m_DisplayFlashedItemsFill; + } + + /** + * Function ReFillLayerWidget + * changes out all the layers in m_Layers and may be called upon + * loading new gerber files. + */ + void ReFillLayerWidget(); + + /** + * Function setActiveLayer + * will change the currently active layer to \a aLayer and also + * update the GERBER_LAYER_WIDGET. + */ + void setActiveLayer( int aLayer, bool doLayerWidgetUpdate = true ); + + /** + * Function getActiveLayer + * returns the active layer + */ + int getActiveLayer(); + + /** + * Function getNextAvailableLayer + * finds the next empty layer starting at \a aLayer and returns it to the caller. If no + * empty layers are found, NO_AVAILABLE_LAYERS is return. + * @param aLayer The first layer to search. + * @return The first empty layer found or NO_AVAILABLE_LAYERS. + */ + int getNextAvailableLayer( int aLayer = 0 ) const; + + bool hasAvailableLayers() const + { + return getNextAvailableLayer() != NO_AVAILABLE_LAYERS; + } + + /** + * Function syncLayerWidget + * updates the currently "selected" layer within the GERBER_LAYER_WIDGET. + * The currently active layer is defined by the return value of getActiveLayer(). + * <p> + * This function cannot be inline without including layer_widget.h in + * here and we do not want to do that. + */ + void syncLayerWidget(); + + /** + * Function syncLayerBox + * updates the currently "selected" layer within m_SelLayerBox + * The currently active layer, as defined by the return value of + * getActiveLayer(). And updates the colored icon in the toolbar. + */ + void syncLayerBox(); + + /** + * Function UpdateTitleAndInfo + * displays the short filename (if exists) of the selected layer + * on the caption of the main GerbView window + * and some other parameters + * Name of the layer (found in the gerber file: LN <name> command) in the status bar + * Name of the Image (found in the gerber file: IN <name> command) in the status bar + * and other data in toolbar + */ + void UpdateTitleAndInfo(); + + /** + * Function GetConfigurationSettings + * Populates the GerbView applications settings list. + * (list of parameters that must be saved in GerbView parameters) + * Currently, only the settings that are needed at start up by the main window are + * defined here. There are other locally used settings scattered throughout the + * GerbView source code (mainly in dialogs). If you need to define a configuration + * setting that need to be loaded at run time, this is the place to define it. + */ + PARAM_CFG_ARRAY& GetConfigurationSettings( void ); + + void LoadSettings( wxConfigBase* aCfg ); // override virtual + + void SaveSettings( wxConfigBase* aCfg ); // override virtual + + void ShowChangedLanguage(); // override EDA_BASE_FRAME virtual + + void Process_Special_Functions( wxCommandEvent& event ); + void OnSelectOptionToolbar( wxCommandEvent& event ); + + /** + * Function OnSelectActiveDCode + * Selects the active DCode for the current active layer. + * Items using this DCode are highlighted. + */ + void OnSelectActiveDCode( wxCommandEvent& event ); + + /** + * Function OnSelectActiveLayer + * Selects the active layer: + * - if a file is loaded, it is loaded in this layer + * _ this layer is displayed on top of other layers + */ + void OnSelectActiveLayer( wxCommandEvent& event ); + + /** + * Function OnShowGerberSourceFile + * Call the preferred editor to show (and edit) the gerber source file + * loaded in the active layer + */ + void OnShowGerberSourceFile( wxCommandEvent& event ); + + /** + * Function OnSelectDisplayMode + * called on a display mode selection + * Mode selection can be fast display, + * or exact mode with stacked images or with transparency + */ + void OnSelectDisplayMode( wxCommandEvent& event ); + + /** + * Function OnQuit + * called on request of application quit + */ + void OnQuit( wxCommandEvent& event ); + + ///> @copydoc EDA_DRAW_FRAME::GetHotKeyDescription() + EDA_HOTKEY* GetHotKeyDescription( int aCommand ) const; + + /** + * Function OnHotKey. + * ** Commands are case insensitive ** + * Some commands are relatives to the item under the mouse cursor + * @param aDC = current device context + * @param aHotkeyCode = hotkey code (ascii or wxWidget code for special keys) + * @param aPosition The cursor position in logical (drawing) units. + * @param aItem = NULL or pointer on a EDA_ITEM under the mouse cursor + */ + bool OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosition, EDA_ITEM* aItem = NULL ); + + GERBER_DRAW_ITEM* GerberGeneralLocateAndDisplay(); + GERBER_DRAW_ITEM* Locate( const wxPoint& aPosition, int typeloc ); + + void Process_Settings( wxCommandEvent& event ); + void Process_Config( wxCommandEvent& event ); + void InstallGerberOptionsDialog( wxCommandEvent& event ); + + void OnUpdateDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateCoordType( wxUpdateUIEvent& aEvent ); + void OnUpdateFlashedItemsDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateLinesDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdatePolygonsDrawMode( wxUpdateUIEvent& aEvent ); + void OnUpdateShowDCodes( wxUpdateUIEvent& aEvent ); + void OnUpdateShowNegativeItems( wxUpdateUIEvent& aEvent ); + void OnUpdateShowLayerManager( wxUpdateUIEvent& aEvent ); + void OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ); + void OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ); + + /** + * Function BlockCommand + * returns the block command (BLOCK_MOVE, BLOCK_COPY...) corresponding to + * the \a aKey (ALT, SHIFT ALT ..) + */ + virtual int BlockCommand( int key ); + + /** + * Function HandleBlockPlace + * handles the block place command. + */ + virtual void HandleBlockPlace( wxDC* DC ); + + /** + * Function HandleBlockEnd( ) + * handles the end of a block command, + * It is called at the end of the definition of the area of a block. + * Depending on the current block command, this command is executed + * or parameters are initialized to prepare a call to HandleBlockPlace + * in GetScreen()->m_BlockLocate + * + * @return false if no item selected, or command finished, + * true if some items found and HandleBlockPlace must be called later. + */ + virtual bool HandleBlockEnd( wxDC* DC ); + + /** + * Function Block_Move + * moves all tracks and segments within the selected block. + * New location is determined by the current offset from the selected + * block's original location. + * Defined separately in Pcbnew and GerbView + * + * @param DC A device context to draw on. + */ + void Block_Move( wxDC* DC ); + + /** + * Function ToPlotter + * Open a dialog frame to create plot and drill files + * relative to the current board + */ + void ToPlotter( wxCommandEvent& event ); + + /** + * Function ToPrinter + * Open a dialog frame to print layers + */ + void ToPrinter( wxCommandEvent& event ); + + void Files_io( wxCommandEvent& event ); + + /** + * Function OnGbrFileHistory + * deletes the current data and loads a Gerber file selected from history list on + * current layer. + */ + void OnGbrFileHistory( wxCommandEvent& event ); + + /** + * Function OnDrlFileHistory + * deletes the current data and load a drill file in Excellon format selected from + * history list on current layer. + */ + void OnDrlFileHistory( wxCommandEvent& event ); + + /** + * function LoadGerberFiles + * Load a photoplot (Gerber) file or many files. + * @param aFileName - void string or file name with full path to open or empty string to + * open a new file. In this case one one file is loaded + * if void string: user will be prompted for filename(s) + * @return true if file was opened successfully. + */ + bool LoadGerberFiles( const wxString& aFileName ); + int ReadGerberFile( FILE* File, bool Append ); + bool Read_GERBER_File( const wxString& GERBER_FullFileName, + const wxString& D_Code_FullFileName ); + + /** + * function LoadDrllFiles + * Load a drill (EXCELLON) file or many files. + * @param aFileName - void string or file name with full path to open or empty string to + * open a new file. In this case one one file is loaded + * if void string: user will be prompted for filename(s) + * @return true if file was opened successfully. + */ + bool LoadExcellonFiles( const wxString& aFileName ); + bool Read_EXCELLON_File( const wxString& aFullFileName ); + + bool GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey = 0 ); + + /** + * Set Size Items (Lines, Flashes) from DCodes List + */ + void CopyDCodesSizeToItems(); + void Liste_D_Codes(); + + // PCB handling + bool Clear_DrawLayers( bool query ); + void Erase_Current_DrawLayer( bool query ); + + // Conversion function + void ExportDataInPcbnewFormat( wxCommandEvent& event ); + + /* SaveCopyInUndoList() virtual + * currently: do nothing in GerbView. + */ + void SaveCopyInUndoList( GERBER_DRAW_ITEM* aItemToCopy, + UNDO_REDO_T aTypeCommand = UR_UNSPECIFIED, + const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) { } + + /** + * Function SaveCopyInUndoList (overloaded). + * Creates a new entry in undo list of commands. + * add a list of pickers to handle a list of items + * @param aItemsList = the list of items modified by the command to undo + * @param aTypeCommand = command type (see enum UNDO_REDO_T) + * @param aTransformPoint = the reference point of the transformation, + * for commands like move + */ + void SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsList, + UNDO_REDO_T aTypeCommand, + const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ) + { + // currently: do nothing in GerbView. + } + + /** Virtual function PrintPage + * used to print a page + * @param aDC = wxDC given by the calling print function + * @param aPrintMasklayer = a 32 bits mask: bit n = 1 -> layer n is printed + * @param aPrintMirrorMode = not used here (Set when printing in mirror mode) + * @param aData = a pointer on an auxiliary data (not always used, NULL if not used) + */ + virtual void PrintPage( wxDC* aDC, LSET aPrintMasklayer, bool aPrintMirrorMode, + void* aData = NULL ); + + /** + * Function DrawItemsDCodeID + * Draw the DCode value (if exists) corresponding to gerber item + * (polygons do not have a DCode) + * @param aDC = the current device context + * @param aDrawMode = GR_COPY, GR_OR ... + */ + void DrawItemsDCodeID( wxDC* aDC, GR_DRAWMODE aDrawMode ); + + DECLARE_EVENT_TABLE() +}; + +#endif /* WX_GERBER_STRUCT_H */ diff --git a/gerbview/gerbview_id.h b/gerbview/gerbview_id.h new file mode 100644 index 0000000..a69cbcd --- /dev/null +++ b/gerbview/gerbview_id.h @@ -0,0 +1,81 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __GERBVIEW_ID_H__ +#define __GERBVIEW_ID_H__ + +#include <id.h> + +/** + * Command IDs for the printed circuit board editor. + * + * Please add IDs that are unique to the gerber file viewer (GerbView) here and not in + * the global id.h file. This will prevent the entire project from being rebuilt when + * adding new commands to the GerbView. + */ + +enum gerbview_ids +{ + ID_MAIN_MENUBAR = ID_END_LIST, + + ID_GERBVIEW_SHOW_LIST_DCODES, + ID_GERBVIEW_LOAD_DRILL_FILE, + ID_GERBVIEW_ERASE_ALL, + ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, + ID_GERBVIEW_SHOW_SOURCE, + ID_GERBVIEW_EXPORT_TO_PCBNEW, + + ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, + + // IDs for drill file history (wxID_FILEnn is already in use) + ID_GERBVIEW_DRILL_FILE, + ID_GERBVIEW_DRILL_FILE1, + ID_GERBVIEW_DRILL_FILE2, + ID_GERBVIEW_DRILL_FILE3, + ID_GERBVIEW_DRILL_FILE4, + ID_GERBVIEW_DRILL_FILE5, + ID_GERBVIEW_DRILL_FILE6, + ID_GERBVIEW_DRILL_FILE7, + ID_GERBVIEW_DRILL_FILE8, + ID_GERBVIEW_DRILL_FILE9, + + ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + ID_GERBVIEW_GLOBAL_DELETE, + ID_GERBVIEW_OPTIONS_SETUP, + ID_GERBVIEW_SET_PAGE_BORDER, + ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + ID_TB_OPTIONS_SHOW_DCODES, + ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, + ID_TB_OPTIONS_SHOW_LINES_SKETCH, + ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, + ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS, + ID_TB_OPTIONS_SHOW_GBR_MODE_0, + ID_TB_OPTIONS_SHOW_GBR_MODE_1, + ID_TB_OPTIONS_SHOW_GBR_MODE_2, + + ID_GERBER_END_LIST +}; + +#endif /* __GERBVIEW_IDS_H__ */ diff --git a/gerbview/hotkeys.cpp b/gerbview/hotkeys.cpp new file mode 100644 index 0000000..eae1ad0 --- /dev/null +++ b/gerbview/hotkeys.cpp @@ -0,0 +1,216 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2010 <Jean-Pierre Charras> + * Copyright (C) 1992-2010 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview/hotkeys.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <kicad_device_context.h> +#include <id.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_drawpanel.h> +#include <hotkeys.h> +#include <gerbview_id.h> + + +/* How to add a new hotkey: + * add a new id in the enum hotkey_id_commnand like MY_NEW_ID_FUNCTION. + * add a new EDA_HOTKEY entry like: + * static EDA_HOTKEY HkMyNewEntry(wxT("Command Label"), MY_NEW_ID_FUNCTION, default key value); + * "Command Label" is the name used in hotkey list display, and the identifier in the + * hotkey list file MY_NEW_ID_FUNCTION is an equivalent id function used in the switch + * in OnHotKey() function. default key value is the default hotkey for this command. + * Can be overrided by the user hotkey list file add the HkMyNewEntry pointer in the + * s_board_edit_Hotkey_List list ( or/and the s_module_edit_Hotkey_List list) Add the + * new code in the switch in OnHotKey() function. when the variable PopupOn is true, + * an item is currently edited. This can be usefull if the new function cannot be + * executed while an item is currently being edited + * ( For example, one cannot start a new wire when a component is moving.) + * + * Note: If an hotkey is a special key, be sure the corresponding wxWidget keycode (WXK_XXXX) + * is handled in the hotkey_name_descr s_Hotkey_Name_List list (see hotkeys_basic.cpp) + * and see this list for some ascii keys (space ...) + */ + +// local variables +// Hotkey list: +static EDA_HOTKEY HkZoomAuto( _HKI( "Zoom Auto" ), HK_ZOOM_AUTO, WXK_HOME ); +static EDA_HOTKEY HkZoomCenter( _HKI( "Zoom Center" ), HK_ZOOM_CENTER, WXK_F4 ); +static EDA_HOTKEY HkZoomRedraw( _HKI( "Zoom Redraw" ), HK_ZOOM_REDRAW, WXK_F3 ); +static EDA_HOTKEY HkZoomOut( _HKI( "Zoom Out" ), HK_ZOOM_OUT, WXK_F2 ); +static EDA_HOTKEY HkZoomIn( _HKI( "Zoom In" ), HK_ZOOM_IN, WXK_F1 ); +static EDA_HOTKEY HkHelp( _HKI( "Help (this window)" ), HK_HELP, '?' ); +static EDA_HOTKEY HkSwitchUnits( _HKI( "Switch Units" ), HK_SWITCH_UNITS, 'U' ); +static EDA_HOTKEY HkResetLocalCoord( _HKI( "Reset Local Coordinates" ), HK_RESET_LOCAL_COORD, ' ' ); + +static EDA_HOTKEY HkLinesDisplayMode( _HKI( "Gbr Lines Display Mode" ), HK_GBR_LINES_DISPLAY_MODE, 'L' ); +static EDA_HOTKEY HkFlashedDisplayMode( _HKI( "Gbr Flashed Display Mode" ), HK_GBR_FLASHED_DISPLAY_MODE, 'F' ); +static EDA_HOTKEY HkPolygonDisplayMode( _HKI( "Gbr Polygons Display Mode" ), HK_GBR_POLYGON_DISPLAY_MODE, 'P' ); +static EDA_HOTKEY HkNegativeObjDisplayMode( _HKI( "Gbr Negative Obj Display Mode" ), HK_GBR_NEGATIVE_DISPLAY_ONOFF, 'N' ); +static EDA_HOTKEY HkDCodesDisplayMode( _HKI( "DCodes Display Mode" ), HK_GBR_DCODE_DISPLAY_ONOFF, 'D' ); + +static EDA_HOTKEY HkSwitch2NextCopperLayer( _HKI( "Switch to Next Layer" ), HK_SWITCH_LAYER_TO_NEXT, '+' ); +static EDA_HOTKEY HkSwitch2PreviousCopperLayer( _HKI( "Switch to Previous Layer" ), HK_SWITCH_LAYER_TO_PREVIOUS, '-' ); + +// List of common hotkey descriptors +EDA_HOTKEY* gerbviewHotkeyList[] = { + &HkHelp, + &HkZoomIn, &HkZoomOut, &HkZoomRedraw, &HkZoomCenter, + &HkZoomAuto, &HkSwitchUnits, &HkResetLocalCoord, + &HkLinesDisplayMode, &HkFlashedDisplayMode, &HkPolygonDisplayMode, + &HkDCodesDisplayMode, &HkNegativeObjDisplayMode, + &HkSwitch2NextCopperLayer, + &HkSwitch2PreviousCopperLayer, + NULL +}; + + +// list of sections and corresponding hotkey list for GerbView (used to create an hotkey +// config file) +static wxString gerbviewSectionTag( wxT( "[gerbview]" ) ); +static wxString gerbviewSectionTitle( _HKI( "Gerbview Hotkeys" ) ); + +struct EDA_HOTKEY_CONFIG GerbviewHokeysDescr[] = +{ + { &gerbviewSectionTag, gerbviewHotkeyList, &gerbviewSectionTitle }, + { NULL, NULL, NULL } +}; + + +EDA_HOTKEY* GERBVIEW_FRAME::GetHotKeyDescription( int aCommand ) const +{ + EDA_HOTKEY* HK_Descr = GetDescriptorFromCommand( aCommand, gerbviewHotkeyList ); + + return HK_Descr; +} + + +bool GERBVIEW_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosition, EDA_ITEM* aItem ) +{ + #define CHANGE( x ) ( x ) = not (x ) + + wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); + cmd.SetEventObject( this ); + + /* Convert lower to upper case (the usual toupper function has problem with non ascii + * codes like function keys */ + if( (aHotkeyCode >= 'a') && (aHotkeyCode <= 'z') ) + aHotkeyCode += 'A' - 'a'; + + EDA_HOTKEY * HK_Descr = GetDescriptorFromHotkey( aHotkeyCode, gerbviewHotkeyList ); + + if( HK_Descr == NULL ) + return false; + + switch( HK_Descr->m_Idcommand ) + { + default: + case HK_NOT_FOUND: + return false; + + case HK_HELP: // Display Current hotkey list + DisplayHotkeyList( this, GerbviewHokeysDescr ); + break; + + case HK_ZOOM_IN: + cmd.SetId( ID_POPUP_ZOOM_IN ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_ZOOM_OUT: + cmd.SetId( ID_POPUP_ZOOM_OUT ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_ZOOM_REDRAW: + cmd.SetId( ID_ZOOM_REDRAW ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_ZOOM_CENTER: + cmd.SetId( ID_POPUP_ZOOM_CENTER ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_ZOOM_AUTO: + cmd.SetId( ID_ZOOM_PAGE ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_RESET_LOCAL_COORD: // Reset the relative coord + GetScreen()->m_O_Curseur = GetCrossHairPosition(); + break; + + case HK_SWITCH_UNITS: + g_UserUnit = (g_UserUnit == INCHES ) ? MILLIMETRES : INCHES; + break; + + case HK_GBR_LINES_DISPLAY_MODE: + CHANGE( m_DisplayOptions.m_DisplayLinesFill ); + m_canvas->Refresh(); + break; + + case HK_GBR_FLASHED_DISPLAY_MODE: + CHANGE( m_DisplayOptions.m_DisplayFlashedItemsFill ); + m_canvas->Refresh( true ); + break; + + case HK_GBR_POLYGON_DISPLAY_MODE: + CHANGE( m_DisplayOptions.m_DisplayPolygonsFill ); + m_canvas->Refresh(); + break; + + case HK_GBR_NEGATIVE_DISPLAY_ONOFF: + SetElementVisibility( NEGATIVE_OBJECTS_VISIBLE, not IsElementVisible( NEGATIVE_OBJECTS_VISIBLE ) ); + m_canvas->Refresh(); + break; + + case HK_GBR_DCODE_DISPLAY_ONOFF: + SetElementVisibility( DCODES_VISIBLE, not IsElementVisible( DCODES_VISIBLE ) ); + m_canvas->Refresh(); + break; + + case HK_SWITCH_LAYER_TO_PREVIOUS: + if( getActiveLayer() > 0 ) + { + setActiveLayer( getActiveLayer() - 1 ); + m_canvas->Refresh(); + } + break; + + case HK_SWITCH_LAYER_TO_NEXT: + if( getActiveLayer() < 31 ) + { + setActiveLayer( getActiveLayer() + 1 ); + m_canvas->Refresh(); + } + break; + } + + return true; +} diff --git a/gerbview/hotkeys.h b/gerbview/hotkeys.h new file mode 100644 index 0000000..206d537 --- /dev/null +++ b/gerbview/hotkeys.h @@ -0,0 +1,51 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * gerbview/hotkeys.h + */ + +#ifndef GERBVIEW_KOTKEYS_H_ +#define GERBVIEW_KOTKEYS_H_ + +#include <hotkeys_basic.h> + +// List of hot keys id. +// see also enum common_hotkey_id_commnand in hotkeys_basic.h +// for shared hotkeys id +enum hotkey_id_commnand { + HK_SWITCH_UNITS = HK_COMMON_END, + HK_GBR_LINES_DISPLAY_MODE, + HK_GBR_FLASHED_DISPLAY_MODE, + HK_GBR_POLYGON_DISPLAY_MODE, + HK_GBR_NEGATIVE_DISPLAY_ONOFF, + HK_GBR_DCODE_DISPLAY_ONOFF, + HK_SWITCH_LAYER_TO_NEXT, + HK_SWITCH_LAYER_TO_PREVIOUS +}; + +// List of hotkey descriptors for GerbView. +extern struct EDA_HOTKEY_CONFIG GerbviewHokeysDescr[]; + +#endif // GERBVIEW_KOTKEYS_H_ diff --git a/gerbview/init_gbr_drawlayers.cpp b/gerbview/init_gbr_drawlayers.cpp new file mode 100644 index 0000000..87773b0 --- /dev/null +++ b/gerbview/init_gbr_drawlayers.cpp @@ -0,0 +1,98 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file init_gbr_drawlayers.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> +#include <confirm.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> +#include <class_gerbview_layer_widget.h> +#include <class_gbr_layout.h> + +bool GERBVIEW_FRAME::Clear_DrawLayers( bool query ) +{ + if( GetGerberLayout() == NULL ) + return false; + + if( query && GetScreen()->IsModify() ) + { + if( !IsOK( this, _( "Current data will be lost?" ) ) ) + return false; + } + + GetGerberLayout()->m_Drawings.DeleteAll(); + + g_GERBER_List.ClearList(); + + GetGerberLayout()->SetBoundingBox( EDA_RECT() ); + + SetScreen( new GBR_SCREEN( GetPageSettings().GetSizeIU() ) ); + + setActiveLayer( 0 ); + m_LayersManager->UpdateLayerIcons(); + syncLayerBox(); + return true; +} + + +void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query ) +{ + int layer = getActiveLayer(); + wxString msg; + + msg.Printf( _( "Clear layer %d?" ), layer + 1 ); + + if( query && !IsOK( this, msg ) ) + return; + + SetCurItem( NULL ); + + GERBER_DRAW_ITEM* item = GetGerberLayout()->m_Drawings; + GERBER_DRAW_ITEM * next; + + for( ; item; item = next ) + { + next = item->Next(); + + if( item->GetLayer() != layer ) + continue; + + item->DeleteStructure(); + } + + g_GERBER_List.ClearImage( layer ); + + GetScreen()->SetModify(); + m_canvas->Refresh(); + m_LayersManager->UpdateLayerIcons(); + syncLayerBox(); +} diff --git a/gerbview/locate.cpp b/gerbview/locate.cpp new file mode 100644 index 0000000..f2fb2a4 --- /dev/null +++ b/gerbview/locate.cpp @@ -0,0 +1,88 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file locate.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <msgpanel.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_gerber_draw_item.h> + + +/* localize a gerber item and return a pointer to it. + * Display info about this item + */ +GERBER_DRAW_ITEM* GERBVIEW_FRAME::Locate( const wxPoint& aPosition, int aTypeloc ) +{ + m_messagePanel->EraseMsgBox(); + wxPoint ref = aPosition; + bool found = false; + + if( aTypeloc == CURSEUR_ON_GRILLE ) + ref = GetNearestGridPosition( ref ); + + int layer = getActiveLayer(); + + // Search first on active layer + GERBER_DRAW_ITEM* gerb_item = GetItemsList(); + + for( ; gerb_item; gerb_item = gerb_item->Next() ) + { + if( gerb_item->GetLayer()!= layer ) + continue; + + if( gerb_item->HitTest( ref ) ) + { + found = true; + break; + } + } + + if( !found ) // Search on all layers + { + for( gerb_item = GetItemsList(); gerb_item; gerb_item = gerb_item->Next() ) + { + if( gerb_item->HitTest( ref ) ) + { + found = true; + break; + } + } + } + + if( found ) + { + MSG_PANEL_ITEMS items; + gerb_item->GetMsgPanelInfo( items ); + SetMsgPanel( items ); + return gerb_item; + } + + return NULL; +} diff --git a/gerbview/menubar.cpp b/gerbview/menubar.cpp new file mode 100644 index 0000000..e9ad2bd --- /dev/null +++ b/gerbview/menubar.cpp @@ -0,0 +1,257 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2009-2013 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview/menubar.cpp + * @brief (Re)Create the main menubar for GerbView + */ +#include <fctsys.h> + +#include <pgm_base.h> +#include <kiface_i.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <gerbview_id.h> +#include <hotkeys.h> +#include <menus_helpers.h> + + +void GERBVIEW_FRAME::ReCreateMenuBar() +{ + // Create and try to get the current menubar + wxMenuBar* menuBar = GetMenuBar(); + + if( !menuBar ) + menuBar = new wxMenuBar(); + + // Delete all existing menus so they can be rebuilt. + // This allows language changes of the menu text on the fly. + menuBar->Freeze(); + + while( menuBar->GetMenuCount() ) + delete menuBar->Remove( 0 ); + + // Recreate all menus: + + // Menu File: + wxMenu* fileMenu = new wxMenu; + + // Load + AddMenuItem( fileMenu, + wxID_FILE, + _( "Load &Gerber File" ), + _( "Load a new Gerber file on the current layer. Previous data will be deleted" ), + KiBitmap( gerber_file_xpm ) ); + + // Excellon + AddMenuItem( fileMenu, + ID_GERBVIEW_LOAD_DRILL_FILE, + _( "Load &EXCELLON Drill File" ), + _( "Load excellon drill file" ), + KiBitmap( gerbview_drill_file_xpm ) ); + + // Recent gerber files + static wxMenu* openRecentGbrMenu; + + // Add this menu to list menu managed by m_fileHistory + // (the file history will be updated when adding/removing files in history + if( openRecentGbrMenu ) + Kiface().GetFileHistory().RemoveMenu( openRecentGbrMenu ); + + openRecentGbrMenu = new wxMenu(); + + Kiface().GetFileHistory().UseMenu( openRecentGbrMenu ); + Kiface().GetFileHistory().AddFilesToMenu(); + + AddMenuItem( fileMenu, openRecentGbrMenu, + wxID_ANY, + _( "Open &Recent Gerber File" ), + _( "Open a recent opened Gerber file" ), + KiBitmap( gerber_recent_files_xpm ) ); + + // Recent drill files + static wxMenu* openRecentDrlMenu; + + if( openRecentDrlMenu ) + m_drillFileHistory.RemoveMenu( openRecentDrlMenu ); + + openRecentDrlMenu = new wxMenu(); + m_drillFileHistory.UseMenu( openRecentDrlMenu ); + m_drillFileHistory.AddFilesToMenu( ); + AddMenuItem( fileMenu, openRecentDrlMenu, + wxID_ANY, + _( "Open Recent Dri&ll File" ), + _( "Open a recent opened drill file" ), + KiBitmap( gerbview_open_recent_drill_files_xpm ) ); + + // Separator + fileMenu->AppendSeparator(); + + // Clear all + AddMenuItem( fileMenu, + ID_GERBVIEW_ERASE_ALL, + _( "Clear &All" ), + _( "Clear all layers. All data will be deleted" ), + KiBitmap( gerbview_clear_layers_xpm ) ); + + // Separator + fileMenu->AppendSeparator(); + + // Export to Pcbnew + AddMenuItem( fileMenu, + ID_GERBVIEW_EXPORT_TO_PCBNEW, + _( "E&xport to Pcbnew" ), + _( "Export data in Pcbnew format" ), + KiBitmap( export_xpm ) ); + + // Separator + fileMenu->AppendSeparator(); + + // Print + AddMenuItem( fileMenu, + wxID_PRINT, + _( "&Print" ), + _( "Print gerber" ), + KiBitmap( print_button_xpm ) ); + + // Separator + fileMenu->AppendSeparator(); + + // Exit + AddMenuItem( fileMenu, + wxID_EXIT, + _( "&Close" ), + _( "Close GerbView" ), + KiBitmap( exit_xpm ) ); + + // Menu for configuration and preferences + wxMenu* configMenu = new wxMenu; + + // Hide layer manager + AddMenuItem( configMenu, + ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + _( "Hide &Layers Manager" ), + m_show_layer_manager_tools ? + _( "Hide &Layers Manager" ) : _("Show &Layers Manager" ), + KiBitmap( layers_manager_xpm ) ); + + // Options (Preferences on WXMAC) + +#ifdef __WXMAC__ + configMenu->Append(wxID_PREFERENCES); +#else + AddMenuItem( configMenu, + wxID_PREFERENCES, + _( "&Options" ), + _( "Set options to draw items" ), + KiBitmap( preference_xpm ) ); +#endif // __WXMAC__ + + // Language submenu + Pgm().AddMenuLanguageList( configMenu ); + + // Hotkey submenu + AddHotkeyConfigMenu( configMenu ); + + // Menu miscellaneous + wxMenu* miscellaneousMenu = new wxMenu; + + // List dcodes + AddMenuItem( miscellaneousMenu, + ID_GERBVIEW_SHOW_LIST_DCODES, + _( "&List DCodes" ), + _( "List and edit D-codes" ), + KiBitmap( show_dcodenumber_xpm ) ); + + // Show source + AddMenuItem( miscellaneousMenu, + ID_GERBVIEW_SHOW_SOURCE, + _( "&Show Source" ), + _( "Show source file for the current layer" ), + KiBitmap( tools_xpm ) ); + + // Separator + miscellaneousMenu->AppendSeparator(); + + // Clear layer + AddMenuItem( miscellaneousMenu, + ID_GERBVIEW_GLOBAL_DELETE, + _( "&Clear Layer" ), + _( "Clear current layer" ), + KiBitmap( general_deletions_xpm ) ); + + // Separator + miscellaneousMenu->AppendSeparator(); + + // Text editor + AddMenuItem( miscellaneousMenu, + ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, + _( "&Text Editor" ), + _( "Select your preferred text editor" ), + KiBitmap( editor_xpm ) ); + + // Menu Help + wxMenu* helpMenu = new wxMenu; + + // Version info + AddHelpVersionInfoMenuEntry( helpMenu ); + + // Contents + AddMenuItem( helpMenu, + wxID_HELP, + _( "Gerbview &Manual" ), + _( "Open the GerbView Manual" ), + KiBitmap( online_help_xpm ) ); + + AddMenuItem( helpMenu, + wxID_INDEX, + _( "&Getting Started in KiCad" ), + _( "Open \"Getting Started in KiCad\" guide for beginners" ), + KiBitmap( help_xpm ) ); + + // Separator + helpMenu->AppendSeparator(); + + // About Kicad + AddMenuItem( helpMenu, + wxID_ABOUT, + _( "&About Kicad" ), + _( "About KiCad" ), + KiBitmap( info_xpm ) ); + + // Append menus to the menubar + menuBar->Append( fileMenu, _( "&File" ) ); + menuBar->Append( configMenu, _( "&Preferences" ) ); + menuBar->Append( miscellaneousMenu, _( "&Miscellaneous" ) ); + menuBar->Append( helpMenu, _( "&Help" ) ); + + menuBar->Thaw(); + + // Associate the menu bar with the frame, if no previous menubar + if( GetMenuBar() == NULL ) + SetMenuBar( menuBar ); + else + menuBar->Refresh(); +} diff --git a/gerbview/onleftclick.cpp b/gerbview/onleftclick.cpp new file mode 100644 index 0000000..55b47df --- /dev/null +++ b/gerbview/onleftclick.cpp @@ -0,0 +1,60 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <class_drawpanel.h> +#include <common.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <gerbview_id.h> +#include <class_GERBER.h> +#include <dialog_helpers.h> +#include <class_DCodeSelectionbox.h> + +/* Process the command triggered by the left button of the mouse + * currently: just display info in the message panel. + */ +void GERBVIEW_FRAME::OnLeftClick( wxDC* DC, const wxPoint& aPosition ) +{ + GERBER_DRAW_ITEM* DrawStruct = Locate( aPosition, CURSEUR_OFF_GRILLE ); + + GetScreen()->SetCurItem( DrawStruct ); + + if( DrawStruct == NULL ) + { + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( getActiveLayer() ); + + if( gerber ) + gerber->DisplayImageInfo( ); + } +} + + +/* Called on a double click of left mouse button. + */ +void GERBVIEW_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& aPosition ) +{ + // Currently: no nothing +} diff --git a/gerbview/onrightclick.cpp b/gerbview/onrightclick.cpp new file mode 100644 index 0000000..8f5cfe3 --- /dev/null +++ b/gerbview/onrightclick.cpp @@ -0,0 +1,95 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <class_drawpanel.h> +#include <id.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <menus_helpers.h> + + +/* Prepare the right-click pullup menu. + * The menu already has a list of zoom commands. + */ +bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu ) +{ + GERBER_DRAW_ITEM* DrawStruct = (GERBER_DRAW_ITEM*) GetScreen()->GetCurItem(); + wxString msg; + bool BlockActive = !GetScreen()->m_BlockLocate.IsIdle(); + bool busy = DrawStruct && DrawStruct->GetFlags(); + + // Do not initiate a start block validation on menu. + m_canvas->SetCanStartBlock( -1 ); + + // Simple location of elements where possible. + if( !busy ) + { + DrawStruct = Locate( aPosition, CURSEUR_OFF_GRILLE ); + busy = DrawStruct && DrawStruct->GetFlags(); + } + + // If command in progress, end command. + if( GetToolId() != ID_NO_TOOL_SELECTED ) + { + if( busy ) + AddMenuItem( PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, + _( "Cancel" ), KiBitmap( cancel_xpm ) ); + else + AddMenuItem( PopMenu, ID_POPUP_CLOSE_CURRENT_TOOL, + _( "End Tool" ), KiBitmap( cursor_xpm ) ); + + PopMenu->AppendSeparator(); + } + else + { + if( busy || BlockActive ) + { + if( BlockActive ) + { + AddMenuItem( PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, + _( "Cancel Block" ), KiBitmap( cancel_xpm ) ); + PopMenu->AppendSeparator(); + AddMenuItem( PopMenu, ID_POPUP_PLACE_BLOCK, + _( "Place Block" ), KiBitmap( checked_ok_xpm ) ); + } + else + { + AddMenuItem( PopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, + _( "Cancel" ), KiBitmap( cancel_xpm ) ); + } + + PopMenu->AppendSeparator(); + } + } + + if( BlockActive ) + return true; + + if( DrawStruct ) + GetScreen()->SetCurItem( DrawStruct ); + + return true; +} diff --git a/gerbview/options.cpp b/gerbview/options.cpp new file mode 100644 index 0000000..741d00f --- /dev/null +++ b/gerbview/options.cpp @@ -0,0 +1,97 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file options.cpp + * @brief Set some general options of GerbView. + */ + + +#include <fctsys.h> +#include <common.h> +#include <class_drawpanel.h> + +#include <gerbview.h> +#include <gerbview_id.h> + + +/** + * Function OnSelectOptionToolbar + * called to validate current choices + */ +void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) +{ + int id = event.GetId(); + bool state; + + switch( id ) + { + case ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG: + state = ! m_show_layer_manager_tools; + id = ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR; + break; + + default: + state = m_optionsToolBar->GetToolToggled( id ); + break; + } + + switch( id ) + { + case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH: + m_DisplayOptions.m_DisplayFlashedItemsFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_LINES_SKETCH: + m_DisplayOptions.m_DisplayLinesFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH: + m_DisplayOptions.m_DisplayPolygonsFill = not state; + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_DCODES: + SetElementVisibility( DCODES_VISIBLE, state ); + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR: + // show/hide auxiliary Vertical layers and visibility manager toolbar + m_show_layer_manager_tools = state; + m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( m_show_layer_manager_tools ); + m_auimgr.Update(); + GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + m_show_layer_manager_tools ? + _("Hide &Layers Manager" ) : _("Show &Layers Manager" )); + break; + + default: + wxMessageBox( wxT( "GERBVIEW_FRAME::OnSelectOptionToolbar error" ) ); + break; + } +} + diff --git a/gerbview/pcbplot.cpp b/gerbview/pcbplot.cpp new file mode 100644 index 0000000..2c7ca24 --- /dev/null +++ b/gerbview/pcbplot.cpp @@ -0,0 +1,36 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <pcbplot.h> + +/** TODO */ +void GERBVIEW_FRAME::ToPlotter(wxCommandEvent& event) +{ +} + diff --git a/gerbview/pcbplot.h b/gerbview/pcbplot.h new file mode 100644 index 0000000..72eeecf --- /dev/null +++ b/gerbview/pcbplot.h @@ -0,0 +1,40 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file gerbview/pcbplot.h + */ + +#ifndef PCBPLOT_H +#define PCBPLOT_H + +/* Shared Config keys for plot and print */ +#define OPTKEY_LAYERBASE wxT( "PlotLayer_%d" ) +#define OPTKEY_PRINT_X_FINESCALE_ADJ wxT( "PrintXFineScaleAdj" ) +#define OPTKEY_PRINT_Y_FINESCALE_ADJ wxT( "PrintYFineScaleAdj" ) +#define OPTKEY_PRINT_SCALE wxT( "PrintScale" ) +#define OPTKEY_PRINT_PAGE_FRAME wxT( "PrintPageFrame" ) +#define OPTKEY_PRINT_MONOCHROME_MODE wxT( "PrintMonochrome" ) + +#endif // ifndef PCBPLOT_H diff --git a/gerbview/printout_control.cpp b/gerbview/printout_control.cpp new file mode 100644 index 0000000..1eb8ad1 --- /dev/null +++ b/gerbview/printout_control.cpp @@ -0,0 +1,269 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file printout_control.cpp + * @brief Board print handler implementation file. + */ + + +// Set this to 1 if you want to test PostScript printing under MSW. +#define wxTEST_POSTSCRIPT_IN_MSW 1 + +#include <fctsys.h> +#include <pgm_base.h> +#include <gr_basic.h> +#include <class_drawpanel.h> +#include <confirm.h> +#include <base_units.h> +#include <wxstruct.h> +#include <class_base_screen.h> +#include <layers_id_colors_and_visibility.h> + +#include <gerbview_frame.h> + +#include <printout_controler.h> + + + +PRINT_PARAMETERS::PRINT_PARAMETERS() +{ + m_PenDefaultSize = Millimeter2iu( 0.2 ); // A reasonable default value to draw items + // which do not have a specified line width + m_PrintScale = 1.0; + m_XScaleAdjust = 1.0; + m_YScaleAdjust = 1.0; + m_Print_Sheet_Ref = false; + m_PrintMaskLayer.set(); + m_PrintMirror = false; + m_Print_Black_and_White = true; + m_OptionPrintPage = 1; + m_PageCount = 1; + m_ForceCentered = false; + m_Flags = 0; + m_DrillShapeOpt = PRINT_PARAMETERS::SMALL_DRILL_SHAPE; + m_PageSetupData = NULL; +} + + +BOARD_PRINTOUT_CONTROLLER::BOARD_PRINTOUT_CONTROLLER( const PRINT_PARAMETERS& aParams, + EDA_DRAW_FRAME* aParent, + const wxString& aTitle ) : + wxPrintout( aTitle ) +{ + m_PrintParams = aParams; // Make a local copy of the print parameters. + m_Parent = aParent; +} + + +bool BOARD_PRINTOUT_CONTROLLER::OnPrintPage( int aPage ) +{ + // in gerbview, draw layers are always printed on separate pages + // because handling negative objects when using only one page is tricky + m_PrintParams.m_Flags = aPage; + DrawPage(); + + return true; +} + + +void BOARD_PRINTOUT_CONTROLLER::GetPageInfo( int* minPage, int* maxPage, + int* selPageFrom, int* selPageTo ) +{ + *minPage = 1; + *selPageFrom = 1; + + int icnt = 1; + + if( m_PrintParams.m_OptionPrintPage == 0 ) + icnt = m_PrintParams.m_PageCount; + + *maxPage = icnt; + *selPageTo = icnt; +} + + +void BOARD_PRINTOUT_CONTROLLER::DrawPage() +{ + wxPoint offset; + double userscale; + EDA_RECT boardBoundingBox; + EDA_RECT drawRect; + wxDC* dc = GetDC(); + BASE_SCREEN* screen = m_Parent->GetScreen(); + bool printMirror = m_PrintParams.m_PrintMirror; + wxSize pageSizeIU = m_Parent->GetPageSizeIU(); + + wxBusyCursor dummy; + + boardBoundingBox = ((GERBVIEW_FRAME*) m_Parent)->GetGerberLayoutBoundingBox(); + wxString titleblockFilename; // TODO see if we uses the gerber file name + + // Use the page size as the drawing area when the board is shown or the user scale + // is less than 1. + if( m_PrintParams.PrintBorderAndTitleBlock() ) + boardBoundingBox = EDA_RECT( wxPoint( 0, 0 ), pageSizeIU ); + + // Compute the PCB size in internal units + userscale = m_PrintParams.m_PrintScale; + + if( m_PrintParams.m_PrintScale == 0 ) // fit in page option + { + if(boardBoundingBox.GetWidth() && boardBoundingBox.GetHeight()) + { + int margin = Millimeter2iu( 10.0 ); // add a margin around the drawings + double scaleX = (double)(pageSizeIU.x - (2 * margin)) / + boardBoundingBox.GetWidth(); + double scaleY = (double)(pageSizeIU.y - (2 * margin)) / + boardBoundingBox.GetHeight(); + userscale = (scaleX < scaleY) ? scaleX : scaleY; + } + else + userscale = 1.0; + } + + wxSize scaledPageSize = pageSizeIU; + drawRect.SetSize( scaledPageSize ); + scaledPageSize.x = wxRound( scaledPageSize.x / userscale ); + scaledPageSize.y = wxRound( scaledPageSize.y / userscale ); + + + if( m_PrintParams.m_PageSetupData ) + { + // Always scale to the size of the paper. + FitThisSizeToPageMargins( scaledPageSize, *m_PrintParams.m_PageSetupData ); + } + + // Compute Accurate scale 1 + if( m_PrintParams.m_PrintScale == 1.0 ) + { + // We want a 1:1 scale, regardless the page setup + // like page size, margin ... + MapScreenSizeToPaper(); // set best scale and offset (scale is not used) + int w, h; + GetPPIPrinter( &w, &h ); + double accurate_Xscale = (double) w / (IU_PER_MILS*1000); + double accurate_Yscale = (double) h / (IU_PER_MILS*1000); + + if( IsPreview() ) // Scale must take in account the DC size in Preview + { + // Get the size of the DC in pixels + wxSize PlotAreaSize; + dc->GetSize( &PlotAreaSize.x, &PlotAreaSize.y ); + GetPageSizePixels( &w, &h ); + accurate_Xscale *= (double)PlotAreaSize.x / w; + accurate_Yscale *= (double)PlotAreaSize.y / h; + } + // Fine scale adjust + accurate_Xscale *= m_PrintParams.m_XScaleAdjust; + accurate_Yscale *= m_PrintParams.m_YScaleAdjust; + + // Set print scale for 1:1 exact scale + dc->SetUserScale( accurate_Xscale, accurate_Yscale ); + } + + // Get the final size of the DC in pixels + wxSize PlotAreaSizeInPixels; + dc->GetSize( &PlotAreaSizeInPixels.x, &PlotAreaSizeInPixels.y ); + + double scalex, scaley; + dc->GetUserScale( &scalex, &scaley ); + + wxSize PlotAreaSizeInUserUnits; + PlotAreaSizeInUserUnits.x = KiROUND( PlotAreaSizeInPixels.x / scalex ); + PlotAreaSizeInUserUnits.y = KiROUND( PlotAreaSizeInPixels.y / scaley ); + + // In some cases the plot origin is the centre of the board outline rather than the center + // of the selected paper size. + if( m_PrintParams.CenterOnBoardOutline() ) + { + // Here we are only drawing the board and it's contents. + drawRect = boardBoundingBox; + offset.x += wxRound( (double) -scaledPageSize.x / 2.0 ); + offset.y += wxRound( (double) -scaledPageSize.y / 2.0 ); + + wxPoint center = boardBoundingBox.Centre(); + + if( printMirror ) + { + // Calculate the mirrored center of the board. + center.x = m_Parent->GetPageSizeIU().x - boardBoundingBox.Centre().x; + } + + offset += center; + } + + GRResetPenAndBrush( dc ); + + EDA_DRAW_PANEL* panel = m_Parent->GetCanvas(); + EDA_RECT tmp = *panel->GetClipBox(); + + // Set clip box to the max size + #define MAX_VALUE (INT_MAX/2) // MAX_VALUE is the max we can use in an integer + // and that allows calculations without overflow + panel->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), wxSize( MAX_VALUE, MAX_VALUE ) ) ); + + screen->m_IsPrinting = true; + EDA_COLOR_T bg_color = m_Parent->GetDrawBgColor(); + + // Print frame reference, if requested, before printing draw layers + if( m_PrintParams.m_Print_Black_and_White ) + GRForceBlackPen( true ); + + if( m_PrintParams.PrintBorderAndTitleBlock() ) + m_Parent->DrawWorkSheet( dc, screen, m_PrintParams.m_PenDefaultSize, + IU_PER_MILS, titleblockFilename ); + + if( printMirror ) + { + // To plot mirror, we reverse the x axis, and modify the plot x origin + dc->SetAxisOrientation( false, false ); + + /* Plot offset x is moved by the x plot area size in order to have + * the old draw area in the new draw area, because the draw origin has not moved + * (this is the upper left corner) but the X axis is reversed, therefore the plotting area + * is the x coordinate values from - PlotAreaSize.x to 0 */ + int x_dc_offset = PlotAreaSizeInPixels.x; + x_dc_offset = KiROUND( x_dc_offset * userscale ); + dc->SetDeviceOrigin( x_dc_offset, 0 ); + + panel->SetClipBox( EDA_RECT( wxPoint( -MAX_VALUE / 2, -MAX_VALUE / 2 ), + panel->GetClipBox()->GetSize() ) ); + } + + // screen->m_DrawOrg = offset; + dc->SetLogicalOrigin( offset.x, offset.y ); + m_Parent->SetDrawBgColor( WHITE ); + + // Never force black pen to print draw layers + // because negative objects need a white pen, not a black pen + // B&W mode is handled in print page function + GRForceBlackPen( false ); + + m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, &m_PrintParams ); + + m_Parent->SetDrawBgColor( bg_color ); + screen->m_IsPrinting = false; + panel->SetClipBox( tmp ); +} diff --git a/gerbview/readgerb.cpp b/gerbview/readgerb.cpp new file mode 100644 index 0000000..3a6f968 --- /dev/null +++ b/gerbview/readgerb.cpp @@ -0,0 +1,199 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> +#include <confirm.h> +#include <kicad_string.h> +#include <gestfich.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <class_GERBER.h> + +#include <html_messagebox.h> +#include <macros.h> + +/* Read a gerber file, RS274D, RS274X or RS274X2 format. + */ +bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName, + const wxString& D_Code_FullFileName ) +{ + int G_command = 0; // command number for G commands like G04 + int D_commande = 0; // command number for D commands like D02 + + char line[GERBER_BUFZ]; + + wxString msg; + char* text; + int layer; // current layer used in GerbView + + layer = getActiveLayer(); + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); + + if( gerber == NULL ) + { + gerber = new GERBER_IMAGE( this, layer ); + g_GERBER_List.AddGbrImage( gerber, layer ); + } + + ClearMessageList( ); + + /* Set the gerber scale: */ + gerber->ResetDefaultValues(); + + /* Read the gerber file */ + gerber->m_Current_File = wxFopen( GERBER_FullFileName, wxT( "rt" ) ); + if( gerber->m_Current_File == 0 ) + { + msg.Printf( _( "File <%s> not found" ), GetChars( GERBER_FullFileName ) ); + DisplayError( this, msg, 10 ); + return false; + } + + gerber->m_FileName = GERBER_FullFileName; + + wxString path = wxPathOnly( GERBER_FullFileName ); + if( path != wxEmptyString ) + wxSetWorkingDirectory( path ); + + LOCALE_IO toggleIo; + + while( true ) + { + if( fgets( line, sizeof(line), gerber->m_Current_File ) == NULL ) + { + if( gerber->m_FilesPtr == 0 ) + break; + + fclose( gerber->m_Current_File ); + + gerber->m_FilesPtr--; + gerber->m_Current_File = + gerber->m_FilesList[gerber->m_FilesPtr]; + + continue; + } + + text = StrPurge( line ); + + while( text && *text ) + { + switch( *text ) + { + case ' ': + case '\r': + case '\n': + text++; + break; + + case '*': // End command + gerber->m_CommandState = END_BLOCK; + text++; + break; + + case 'M': // End file + gerber->m_CommandState = CMD_IDLE; + while( *text ) + text++; + break; + + case 'G': /* Line type Gxx : command */ + G_command = gerber->GCodeNumber( text ); + gerber->Execute_G_Command( text, G_command ); + break; + + case 'D': /* Line type Dxx : Tool selection (xx > 0) or + * command if xx = 0..9 */ + D_commande = gerber->DCodeNumber( text ); + gerber->Execute_DCODE_Command( text, D_commande ); + break; + + case 'X': + case 'Y': /* Move or draw command */ + gerber->m_CurrentPos = gerber->ReadXYCoord( text ); + if( *text == '*' ) // command like X12550Y19250* + { + gerber->Execute_DCODE_Command( text, + gerber->m_Last_Pen_Command ); + } + break; + + case 'I': + case 'J': /* Auxiliary Move command */ + gerber->m_IJPos = gerber->ReadIJCoord( text ); + if( *text == '*' ) // command like X35142Y15945J504* + { + gerber->Execute_DCODE_Command( text, + gerber->m_Last_Pen_Command ); + } + break; + + case '%': + if( gerber->m_CommandState != ENTER_RS274X_CMD ) + { + gerber->m_CommandState = ENTER_RS274X_CMD; + gerber->ReadRS274XCommand( line, text ); + } + else //Error + { + ReportMessage( wxT("Expected RS274X Command") ); + gerber->m_CommandState = CMD_IDLE; + text++; + } + break; + + default: + text++; + msg.Printf( wxT("Unexpected symbol <%c>"), *text ); + ReportMessage( msg ); + break; + } + } + } + + fclose( gerber->m_Current_File ); + + gerber->m_InUse = true; + + // Display errors list + if( m_Messages.size() > 0 ) + { + HTML_MESSAGE_BOX dlg( this, _("Errors") ); + dlg.ListSet(m_Messages); + dlg.ShowModal(); + } + + /* if the gerber file is only a RS274D file + * (i.e. without any aperture information), wran the user: + */ + if( !gerber->m_Has_DCode ) + { + msg = _("Warning: this file has no D-Code definition\n" + "It is perhaps an old RS274D file\n" + "Therefore the size of items is undefined"); + wxMessageBox( msg ); + } + + return true; +} diff --git a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp new file mode 100644 index 0000000..f9a2fb7 --- /dev/null +++ b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp @@ -0,0 +1,305 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> + +#include <gerbview.h> +#include <macros.h> +#include <class_GERBER.h> +#include <base_units.h> + + +/* These routines read the text string point from Text. + * On exit, Text points the beginning of the sequence unread + */ + +// convertion scale from gerber file units to Gerbview internal units +// depending on the gerber file format +// this scale list assumes gerber units are imperial. +// for metric gerber units, the imperial to metric conversion is made in read functions +#define SCALE_LIST_SIZE 9 +static double scale_list[SCALE_LIST_SIZE] = +{ + 1000.0 * IU_PER_MILS, // x.1 format (certainly useless) + 100.0 * IU_PER_MILS, // x.2 format (certainly useless) + 10.0 * IU_PER_MILS, // x.3 format + 1.0 * IU_PER_MILS, // x.4 format + 0.1 * IU_PER_MILS, // x.5 format + 0.01 * IU_PER_MILS, // x.6 format + 0.001 * IU_PER_MILS, // x.7 format (currently the max allowed precision) + 0.0001 * IU_PER_MILS, // provided, but not used + 0.00001 * IU_PER_MILS, // provided, but not used +}; + +/* + * Function scale + * converts a coordinate given in floating point to Gerbvies internal units + * (currently = 10 nanometers) + */ +int scaletoIU( double aCoord, bool isMetric ) +{ + int ret; + + if( isMetric ) // gerber are units in mm + ret = KiROUND( aCoord * IU_PER_MM ); + else // gerber are units in inches + ret = KiROUND( aCoord * IU_PER_MILS * 1000.0 ); + + return ret; +} + + +wxPoint GERBER_IMAGE::ReadXYCoord( char*& Text ) +{ + wxPoint pos; + int type_coord = 0, current_coord, nbdigits; + bool is_float = m_DecimalFormat; + char* text; + char line[256]; + + + if( m_Relative ) + pos.x = pos.y = 0; + else + pos = m_CurrentPos; + + if( Text == NULL ) + return pos; + + text = line; + while( *Text ) + { + if( (*Text == 'X') || (*Text == 'Y') ) + { + type_coord = *Text; + Text++; + text = line; + nbdigits = 0; + + while( IsNumber( *Text ) ) + { + if( *Text == '.' ) // Force decimat format if reading a floating point number + is_float = true; + + // count digits only (sign and decimal point are not counted) + if( (*Text >= '0') && (*Text <='9') ) + nbdigits++; + *(text++) = *(Text++); + } + + *text = 0; + + if( is_float ) + { + // When X or Y values are float numbers, they are given in mm or inches + if( m_GerbMetric ) // units are mm + current_coord = KiROUND( atof( line ) * IU_PER_MILS / 0.0254 ); + else // units are inches + current_coord = KiROUND( atof( line ) * IU_PER_MILS * 1000 ); + } + else + { + int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y; + + if( m_NoTrailingZeros ) + { + int min_digit = + (type_coord == 'X') ? m_FmtLen.x : m_FmtLen.y; + while( nbdigits < min_digit ) + { + *(text++) = '0'; + nbdigits++; + } + + *text = 0; + } + + current_coord = atoi( line ); + double real_scale = scale_list[fmt_scale]; + + if( m_GerbMetric ) + real_scale = real_scale / 25.4; + + current_coord = KiROUND( current_coord * real_scale ); + } + + if( type_coord == 'X' ) + pos.x = current_coord; + else if( type_coord == 'Y' ) + pos.y = current_coord; + + continue; + } + else + break; + } + + if( m_Relative ) + { + pos.x += m_CurrentPos.x; + pos.y += m_CurrentPos.y; + } + + m_CurrentPos = pos; + return pos; +} + + +/* Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm) + * These coordinates are relative, so if coordinate is absent, it's value + * defaults to 0 + */ +wxPoint GERBER_IMAGE::ReadIJCoord( char*& Text ) +{ + wxPoint pos( 0, 0 ); + + int type_coord = 0, current_coord, nbdigits; + bool is_float = false; + char* text; + char line[256]; + + if( Text == NULL ) + return pos; + + text = line; + while( *Text ) + { + if( (*Text == 'I') || (*Text == 'J') ) + { + type_coord = *Text; + Text++; + text = line; + nbdigits = 0; + while( IsNumber( *Text ) ) + { + if( *Text == '.' ) + is_float = true; + + // count digits only (sign and decimal point are not counted) + if( (*Text >= '0') && (*Text <='9') ) + nbdigits++; + + *(text++) = *(Text++); + } + + *text = 0; + if( is_float ) + { + // When X or Y values are float numbers, they are given in mm or inches + if( m_GerbMetric ) // units are mm + current_coord = KiROUND( atof( line ) * IU_PER_MILS / 0.0254 ); + else // units are inches + current_coord = KiROUND( atof( line ) * IU_PER_MILS * 1000 ); + } + else + { + int fmt_scale = + (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y; + + if( m_NoTrailingZeros ) + { + int min_digit = + (type_coord == 'I') ? m_FmtLen.x : m_FmtLen.y; + while( nbdigits < min_digit ) + { + *(text++) = '0'; + nbdigits++; + } + + *text = 0; + } + + current_coord = atoi( line ); + + double real_scale = scale_list[fmt_scale]; + + if( m_GerbMetric ) + real_scale = real_scale / 25.4; + + current_coord = KiROUND( current_coord * real_scale ); + } + if( type_coord == 'I' ) + pos.x = current_coord; + else if( type_coord == 'J' ) + pos.y = current_coord; + + continue; + } + else + break; + } + + m_IJPos = pos; + return pos; +} + + +// Helper functions: + +/** + * Function ReadInt + * reads an int from an ASCII character buffer. If there is a comma after the + * int, then skip over that. + * @param text A reference to a character pointer from which bytes are read + * and the pointer is advanced for each byte read. + * @param aSkipSeparator = true (default) to skip comma + * @return int - The int read in. + */ +int ReadInt( char*& text, bool aSkipSeparator = true ) +{ + int ret = (int) strtol( text, &text, 10 ); + + if( *text == ',' || isspace( *text ) ) + { + if( aSkipSeparator ) + ++text; + } + + return ret; +} + + +/** + * Function ReadDouble + * reads a double from an ASCII character buffer. If there is a comma after + * the double, then skip over that. + * @param text A reference to a character pointer from which the ASCII double + * is read from and the pointer advanced for each character read. + * @param aSkipSeparator = true (default) to skip comma + * @return double + */ +double ReadDouble( char*& text, bool aSkipSeparator = true ) +{ + double ret = strtod( text, &text ); + + if( *text == ',' || isspace( *text ) ) + { + if( aSkipSeparator ) + ++text; + } + + return ret; +} + diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp new file mode 100644 index 0000000..3d8ec54 --- /dev/null +++ b/gerbview/rs274d.cpp @@ -0,0 +1,771 @@ +/** + * @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. + * + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <common.h> + +#include <gerbview.h> +#include <gerbview_frame.h> +#include <trigo.h> +#include <macros.h> +#include <class_gerber_draw_item.h> +#include <class_GERBER.h> +#include <class_X2_gerber_attributes.h> + +#include <cmath> + +/* Gerber: NOTES about some important commands found in RS274D and RS274X (G codes): + * Gn = + * G01 linear interpolation (right trace) + * G02, G20, G21 Circular interpolation, meaning trig <0 (clockwise) + * G03, G30, G31 Circular interpolation, meaning trigo> 0 (counterclockwise) + * G04 = comment. Since Sept 2014, file attributes can be found here + * if the line starts by G04 #@! + * G06 parabolic interpolation + * G07 Cubic Interpolation + * G10 linear interpolation (scale x10) + * G11 linear interpolation (0.1x range) + * G12 linear interpolation (0.01x scale) + * G36 Start polygon mode + * G37 Stop polygon mode (and close it) + * G54 Selection Tool + * G60 linear interpolation (scale x100) + * G70 Select Units = Inches + * G71 Select Units = Millimeters + * G74 disable 360 degrees circular interpolation (return to 90 deg mode) + * and perhaps circular interpolation (return to linear interpolation ) + * see rs274xrevd_e.pdf pages 47 and 48 + * Unfortunately page 47 said G74 disable G02 or G03 + * and page 48 said G01 must be used to disable G02 or G03. + * Currently GerbView disable G02 or G03 after a G74 command (tests using 2 gerber files). + * G75 enable 360 degrees circular interpolation + * G90 mode absolute coordinates + * + * X, Y + * X and Y are followed by + or - and m + n digits (not separated) + * m = integer part + * n = part after the comma + * Classic formats: m = 2, n = 3 (size 2.3) + * m = 3, n = 4 (size 3.4) + * eg + * GxxX00345Y-06123* + * + * Tools and D_CODES + * Tool number (identification of shapes) + * 10 to 999 + * D_CODES: + * D01 ... D9 = command codes: + * D01 = activating light (pen down) when placement + * D02 = light extinction (pen up) when placement + * D03 = Flash + * D09 = VAPE Flash (I never see this command in gerber file) + * D51 = G54 preceded by -> Select VAPE + * + * D10 ... D999 = Identification Tool: tool selection + */ + + +/* Local Functions (are lower case since they are private to this source file) +**/ + + +/** + * Function fillFlashedGBRITEM + * initializes a given GBRITEM so that it can draw a circle which is filled and + * has no pen border. + * + * @param aGbrItem The GBRITEM to fill in. + * @param aAperture the associated type of aperture + * @param Dcode_index The DCODE value, like D14 + * @param aLayer The layer index to set into the GBRITEM + * @param aPos The center point of the flash + * @param aSize The diameter of the round flash + * @param aLayerNegative = true if the current layer is negative + */ +void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem, + APERTURE_T aAperture, + int Dcode_index, + int aLayer, + const wxPoint& aPos, + wxSize aSize, + bool aLayerNegative ) +{ + aGbrItem->SetLayer( aLayer ); + aGbrItem->m_Size = aSize; + aGbrItem->m_Start = aPos; + aGbrItem->m_End = aGbrItem->m_Start; + aGbrItem->m_DCode = Dcode_index; + aGbrItem->SetLayerPolarity( aLayerNegative ); + aGbrItem->m_Flashed = true; + switch( aAperture ) + { + case APT_POLYGON: // flashed regular polygon + aGbrItem->m_Shape = GBR_SPOT_POLY; + break; + + case APT_CIRCLE: + aGbrItem->m_Shape = GBR_SPOT_CIRCLE; + aGbrItem->m_Size.y = aGbrItem->m_Size.x; + break; + + case APT_OVAL: + aGbrItem->m_Shape = GBR_SPOT_OVAL; + break; + + case APT_RECT: + aGbrItem->m_Shape = GBR_SPOT_RECT; + break; + + case APT_MACRO: + aGbrItem->m_Shape = GBR_SPOT_MACRO; + break; + } +} + + +/** + * Function fillLineGBRITEM + * initializes a given GBRITEM so that it can draw a linear D code. + * + * @param aGbrItem The GERBER_DRAW_ITEM to fill in. + * @param Dcode_index The DCODE value, like D14 + * @param aLayer The layer index to set into the GBRITEM + * @param aStart The starting point of the line + * @param aEnd The ending point of the line + * @param aPenSize The size of the flash. Note rectangular shapes are legal. + * @param aLayerNegative = true if the current layer is negative + */ +void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, + int Dcode_index, + int aLayer, + const wxPoint& aStart, + const wxPoint& aEnd, + wxSize aPenSize, + bool aLayerNegative ) +{ + aGbrItem->SetLayer( aLayer ); + aGbrItem->m_Flashed = false; + + aGbrItem->m_Size = aPenSize; + + aGbrItem->m_Start = aStart; + aGbrItem->m_End = aEnd; + + aGbrItem->m_DCode = Dcode_index; + aGbrItem->SetLayerPolarity( aLayerNegative ); +} + + +/** + * Function fillArcGBRITEM + * initializes a given GBRITEM so that it can draw an arc G code. + * <p> + * if multiquadrant == true : arc can be 0 to 360 degrees + * and \a rel_center is the center coordinate relative to start point. + * <p> + * if multiquadrant == false arc can be only 0 to 90 deg, + * and only in the same quadrant : + * <ul> + * <li> absolute angle 0 to 90 (quadrant 1) or + * <li> absolute angle 90 to 180 (quadrant 2) or + * <li> absolute angle 180 to 270 (quadrant 3) or + * <li> absolute angle 270 to 0 (quadrant 4) + * </ul><p> + * @param aGbrItem is the GBRITEM to fill in. + * @param Dcode_index is the DCODE value, like D14 + * @param aLayer is the layer index to set into the GBRITEM + * @param aStart is the starting point + * @param aEnd is the ending point + * @param aRelCenter is the center coordinate relative to start point, + * given in ABSOLUTE VALUE and the sign of values x et y de rel_center + * must be calculated from the previously given constraint: arc only in the + * same quadrant. + * @param aClockwise true if arc must be created clockwise + * @param aPenSize The size of the flash. Note rectangular shapes are legal. + * @param aMultiquadrant = true to create arcs upto 360 deg, + * false when arc is inside one quadrant + * @param aLayerNegative = true if the current layer is negative + */ +static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer, + const wxPoint& aStart, const wxPoint& aEnd, + const wxPoint& aRelCenter, wxSize aPenSize, + bool aClockwise, bool aMultiquadrant, + bool aLayerNegative ) +{ + wxPoint center, delta; + + aGbrItem->m_Shape = GBR_ARC; + aGbrItem->SetLayer( aLayer ); + aGbrItem->m_Size = aPenSize; + aGbrItem->m_Flashed = false; + + if( aMultiquadrant ) + center = aStart + aRelCenter; + else + { + // in single quadrant mode the relative coordinate aRelCenter is always >= 0 + // So we must recalculate the actual sign of aRelCenter.x and aRelCenter.y + center = aRelCenter; + + // calculate arc end coordinate relative to the starting point, + // because center is relative to the center point + delta = aEnd - aStart; + + // now calculate the relative to aStart center position, for a draw function + // that use trigonometric arc angle (or counter-clockwise) + /* Quadrants: + * Y + * 2 | 1 + * -------X + * 3 | 4 + * C = actual relative arc center, S = arc start (axis origin) E = relative arc end + */ + if( (delta.x >= 0) && (delta.y >= 0) ) + { + /* Quadrant 1 (trigo or cclockwise): + * C | E + * ---S--- + * 3 | 4 + */ + center.x = -center.x; + } + else if( (delta.x >= 0) && (delta.y < 0) ) + { + /* Quadrant 4 (trigo or cclockwise): + * 2 | C + * ---S--- + * 3 | E + */ + // Nothing to do + } + else if( (delta.x < 0) && (delta.y >= 0) ) + { + /* Quadrant 2 (trigo or cclockwise): + * E | 1 + * ---S--- + * C | 4 + */ + center.x = -center.x; + center.y = -center.y; + } + else + { + /* Quadrant 3 (trigo or cclockwise): + * 2 | 1 + * ---S--- + * E | C + */ + center.y = -center.y; + } + + // Due to your draw arc function, we need this: + if( !aClockwise ) + center = - center; + + // Calculate actual arc center coordinate: + center += aStart; + } + + if( aClockwise ) + { + aGbrItem->m_Start = aStart; + aGbrItem->m_End = aEnd; + } + else + { + aGbrItem->m_Start = aEnd; + aGbrItem->m_End = aStart; + } + + aGbrItem->m_ArcCentre = center; + + aGbrItem->m_DCode = Dcode_index; + aGbrItem->SetLayerPolarity( aLayerNegative ); +} + + +/** + * Function fillArcPOLY + * creates an arc G code when found in poly outlines. + * <p> + * if multiquadrant == true : arc can be 0 to 360 degrees + * and \a rel_center is the center coordinate relative to start point. + * <p> + * if multiquadrant == false arc can be only 0 to 90 deg, + * and only in the same quadrant : + * <ul> + * <li> absolute angle 0 to 90 (quadrant 1) or + * <li> absolute angle 90 to 180 (quadrant 2) or + * <li> absolute angle 180 to 270 (quadrant 3) or + * <li> absolute angle 270 to 0 (quadrant 4) + * </ul><p> + * @param aGbrItem is the GBRITEM to fill in. + * @param aStart is the starting point + * @param aEnd is the ending point + * @param rel_center is the center coordinate relative to start point, + * given in ABSOLUTE VALUE and the sign of values x et y de rel_center + * must be calculated from the previously given constraint: arc only in the + * same quadrant. + * @param aClockwise true if arc must be created clockwise + * @param aMultiquadrant = true to create arcs upto 360 deg, + * false when arc is inside one quadrant + * @param aLayerNegative = true if the current layer is negative + */ +static void fillArcPOLY( GERBER_DRAW_ITEM* aGbrItem, + const wxPoint& aStart, const wxPoint& aEnd, + const wxPoint& rel_center, + bool aClockwise, bool aMultiquadrant, + bool aLayerNegative ) +{ + /* in order to calculate arc parameters, we use fillArcGBRITEM + * so we muse create a dummy track and use its geometric parameters + */ + static GERBER_DRAW_ITEM dummyGbrItem( NULL, NULL ); + static const int drawlayer = 0; + + aGbrItem->SetLayerPolarity( aLayerNegative ); + + fillArcGBRITEM( &dummyGbrItem, 0, drawlayer, + aStart, aEnd, rel_center, wxSize(0, 0), + aClockwise, aMultiquadrant, aLayerNegative ); + + wxPoint center; + center = dummyGbrItem.m_ArcCentre; + + // Calculate coordinates relative to arc center; + wxPoint start = dummyGbrItem.m_Start - center; + wxPoint end = dummyGbrItem.m_End - center; + + /* Calculate angle arc + * angles are in 0.1 deg + * angle is trigonometrical (counter-clockwise), + * and axis is the X,Y gerber coordinates + */ + double start_angle = ArcTangente( start.y, start.x ); + double end_angle = ArcTangente( end.y, end.x ); + + // dummyTrack has right geometric parameters, but + // fillArcGBRITEM calculates arc parameters for a draw function that expects + // start_angle < end_angle. So ensure this is the case here: + // Due to the fact atan2 returns angles between -180 to + 180 degrees, + // this is not always the case ( a modulo 360.0 degrees can be lost ) + if( start_angle > end_angle ) + end_angle += 3600; + + double arc_angle = start_angle - end_angle; + // Approximate arc by 36 segments per 360 degree + const int increment_angle = 3600 / 36; + int count = std::abs( arc_angle / increment_angle ); + + // calculate polygon corners + // when arc is counter-clockwise, dummyGbrItem arc goes from end to start + // and we must always create a polygon from start to end. + wxPoint start_arc = start; + for( int ii = 0; ii <= count; ii++ ) + { + double rot; + wxPoint end_arc = start; + if( aClockwise ) + rot = ii * increment_angle; // rot is in 0.1 deg + else + rot = (count - ii) * increment_angle; // rot is in 0.1 deg + + if( ii < count ) + RotatePoint( &end_arc, -rot ); + else // last point + end_arc = aClockwise ? end : start; + + aGbrItem->m_PolyCorners.push_back( end_arc + center ); + + start_arc = end_arc; + } +} + + +/* Read the Gnn sequence and returns the value nn. + */ +int GERBER_IMAGE::GCodeNumber( char*& Text ) +{ + int ii = 0; + char* text; + char line[1024]; + + if( Text == NULL ) + return 0; + Text++; + text = line; + while( IsNumber( *Text ) ) + { + *(text++) = *(Text++); + } + + *text = 0; + ii = atoi( line ); + return ii; +} + + +/* Get the sequence Dnn and returns the value nn + */ +int GERBER_IMAGE::DCodeNumber( char*& Text ) +{ + int ii = 0; + char* text; + char line[1024]; + + if( Text == NULL ) + return 0; + + Text++; + text = line; + while( IsNumber( *Text ) ) + *(text++) = *(Text++); + + *text = 0; + ii = atoi( line ); + return ii; +} + + +bool GERBER_IMAGE::Execute_G_Command( char*& text, int G_command ) +{ +// D( printf( "%22s: G_CODE<%d>\n", __func__, G_command ); ) + + switch( G_command ) + { + case GC_PHOTO_MODE: // can starts a D03 flash command: redundant, can + // be safely ignored + break; + + case GC_LINEAR_INTERPOL_1X: + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; + break; + + case GC_CIRCLE_NEG_INTERPOL: + m_Iterpolation = GERB_INTERPOL_ARC_NEG; + break; + + case GC_CIRCLE_POS_INTERPOL: + m_Iterpolation = GERB_INTERPOL_ARC_POS; + break; + + case GC_COMMENT: + // Skip comment, but only if the line does not start by "G04 #@! TF" + // which is a metadata + if( strncmp( text, " #@! TF", 7 ) == 0 ) + { + text += 7; + X2_ATTRIBUTE dummy; + dummy.ParseAttribCmd( m_Current_File, NULL, 0, text ); + if( dummy.IsFileFunction() ) + { + delete m_FileFunction; + m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy ); + } + } + + while ( *text && (*text != '*') ) + text++; + break; + + case GC_LINEAR_INTERPOL_10X: + m_Iterpolation = GERB_INTERPOL_LINEAR_10X; + break; + + case GC_LINEAR_INTERPOL_0P1X: + m_Iterpolation = GERB_INTERPOL_LINEAR_01X; + break; + + case GC_LINEAR_INTERPOL_0P01X: + m_Iterpolation = GERB_INTERPOL_LINEAR_001X; + break; + + case GC_SELECT_TOOL: + { + int D_commande = DCodeNumber( text ); + if( D_commande < FIRST_DCODE ) + return false; + if( D_commande > (TOOLS_MAX_COUNT - 1) ) + D_commande = TOOLS_MAX_COUNT - 1; + m_Current_Tool = D_commande; + D_CODE* pt_Dcode = GetDCODE( D_commande, false ); + if( pt_Dcode ) + pt_Dcode->m_InUse = true; + break; + } + + case GC_SPECIFY_INCHES: + m_GerbMetric = false; // false = Inches, true = metric + break; + + case GC_SPECIFY_MILLIMETERS: + m_GerbMetric = true; // false = Inches, true = metric + break; + + case GC_TURN_OFF_360_INTERPOL: // disable Multi cadran arc and Arc interpol + m_360Arc_enbl = false; + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // not sure it should be done + break; + + case GC_TURN_ON_360_INTERPOL: + m_360Arc_enbl = true; + break; + + case GC_SPECIFY_ABSOLUES_COORD: + m_Relative = false; // false = absolute Coord, true = relative + // Coord + break; + + case GC_SPECIFY_RELATIVEES_COORD: + m_Relative = true; // false = absolute Coord, true = relative + // Coord + break; + + case GC_TURN_ON_POLY_FILL: + m_PolygonFillMode = true; + break; + + case GC_TURN_OFF_POLY_FILL: + if( m_Exposure && m_Parent->GetGerberLayout()->m_Drawings ) // End of polygon + { + GERBER_DRAW_ITEM * gbritem = m_Parent->GetGerberLayout()->m_Drawings.GetLast(); + StepAndRepeatItem( *gbritem ); + } + m_Exposure = false; + m_PolygonFillMode = false; + m_PolygonFillModeState = 0; + break; + + case GC_MOVE: // Non existent + default: + { + wxString msg; + msg.Printf( wxT( "G%0.2d command not handled" ), G_command ); + ReportMessage( msg ); + return false; + } + } + + + return true; +} + + +bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) +{ + wxSize size( 15, 15 ); + + APERTURE_T aperture = APT_CIRCLE; + GERBER_DRAW_ITEM* gbritem; + GBR_LAYOUT* layout = m_Parent->GetGerberLayout(); + + int activeLayer = m_Parent->getActiveLayer(); + + int dcode = 0; + D_CODE* tool = NULL; + wxString msg; + +// D( printf( "%22s: D_CODE<%d>\n", __func__, D_commande ); ) + + if( D_commande >= FIRST_DCODE ) // This is a "Set tool" command + { + if( D_commande > (TOOLS_MAX_COUNT - 1) ) + D_commande = TOOLS_MAX_COUNT - 1; + + // remember which tool is selected, nothing is done with it in this + // call + m_Current_Tool = D_commande; + + D_CODE* pt_Dcode = GetDCODE( D_commande, false ); + if( pt_Dcode ) + pt_Dcode->m_InUse = true; + + return true; + } + else // D_commande = 0..9: this is a pen command (usually D1, D2 or D3) + { + m_Last_Pen_Command = D_commande; + } + + if( m_PolygonFillMode ) // Enter a polygon description: + { + switch( D_commande ) + { + case 1: // code D01 Draw line, exposure ON + if( !m_Exposure ) + { + m_Exposure = true; + gbritem = new GERBER_DRAW_ITEM( layout, this ); + layout->m_Drawings.Append( gbritem ); + gbritem->m_Shape = GBR_POLYGON; + gbritem->SetLayer( activeLayer ); + gbritem->m_Flashed = false; + } + + switch( m_Iterpolation ) + { + case GERB_INTERPOL_ARC_NEG: + case GERB_INTERPOL_ARC_POS: + gbritem = layout->m_Drawings.GetLast(); + + // D( printf( "Add arc poly %d,%d to %d,%d fill %d interpol %d 360_enb %d\n", + // m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x, + // m_CurrentPos.y, m_PolygonFillModeState, +// m_Iterpolation, m_360Arc_enbl ); ) + fillArcPOLY( gbritem, m_PreviousPos, + m_CurrentPos, m_IJPos, + ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? false : true, + m_360Arc_enbl, GetLayerParams().m_LayerNegative ); + break; + + default: + gbritem = layout->m_Drawings.GetLast(); + +// D( printf( "Add poly edge %d,%d to %d,%d fill %d\n", +// m_PreviousPos.x, m_PreviousPos.y, +// m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); ) + + gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage + if( gbritem->m_PolyCorners.size() == 0 ) + gbritem->m_PolyCorners.push_back( gbritem->m_Start ); + + gbritem->m_End = m_CurrentPos; // m_End is used as temporary storage + gbritem->m_PolyCorners.push_back( gbritem->m_End ); + break; + } + + m_PreviousPos = m_CurrentPos; + m_PolygonFillModeState = 1; + break; + + case 2: // code D2: exposure OFF (i.e. "move to") + if( m_Exposure && layout->m_Drawings ) // End of polygon + { + gbritem = layout->m_Drawings.GetLast(); + StepAndRepeatItem( *gbritem ); + } + m_Exposure = false; + m_PreviousPos = m_CurrentPos; + m_PolygonFillModeState = 0; + break; + + default: + return false; + } + } + else + { + switch( D_commande ) + { + case 1: // code D01 Draw line, exposure ON + m_Exposure = true; + + tool = GetDCODE( m_Current_Tool, false ); + if( tool ) + { + size = tool->m_Size; + dcode = tool->m_Num_Dcode; + aperture = tool->m_Shape; + } + + switch( m_Iterpolation ) + { + case GERB_INTERPOL_LINEAR_1X: + gbritem = new GERBER_DRAW_ITEM( layout, this ); + layout->m_Drawings.Append( gbritem ); + +// D( printf( "Add line %d,%d to %d,%d\n", +// m_PreviousPos.x, m_PreviousPos.y, +// m_CurrentPos.x, m_CurrentPos.y ); ) + fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, + m_CurrentPos, size, GetLayerParams().m_LayerNegative ); + StepAndRepeatItem( *gbritem ); + break; + + case GERB_INTERPOL_LINEAR_01X: + case GERB_INTERPOL_LINEAR_001X: + case GERB_INTERPOL_LINEAR_10X: + wxBell(); + break; + + case GERB_INTERPOL_ARC_NEG: + case GERB_INTERPOL_ARC_POS: + gbritem = new GERBER_DRAW_ITEM( layout, this ); + layout->m_Drawings.Append( gbritem ); + +// D( printf( "Add arc %d,%d to %d,%d center %d, %d interpol %d 360_enb %d\n", +// m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x, +// m_CurrentPos.y, m_IJPos.x, +// m_IJPos.y, m_Iterpolation, m_360Arc_enbl ); ) + fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, + m_CurrentPos, m_IJPos, size, + ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? + false : true, m_360Arc_enbl, GetLayerParams().m_LayerNegative ); + StepAndRepeatItem( *gbritem ); + break; + + default: + msg.Printf( wxT( "RS274D: DCODE Command: interpol error (type %X)" ), + m_Iterpolation ); + ReportMessage( msg ); + break; + } + + m_PreviousPos = m_CurrentPos; + break; + + case 2: // code D2: exposure OFF (i.e. "move to") + m_Exposure = false; + m_PreviousPos = m_CurrentPos; + break; + + case 3: // code D3: flash aperture + tool = GetDCODE( m_Current_Tool, false ); + if( tool ) + { + size = tool->m_Size; + dcode = tool->m_Num_Dcode; + aperture = tool->m_Shape; + } + + gbritem = new GERBER_DRAW_ITEM( layout, this ); + layout->m_Drawings.Append( gbritem ); + fillFlashedGBRITEM( gbritem, aperture, + dcode, activeLayer, m_CurrentPos, + size, GetLayerParams().m_LayerNegative ); + StepAndRepeatItem( *gbritem ); + m_PreviousPos = m_CurrentPos; + break; + + default: + return false; + } + } + + return true; +} diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp new file mode 100644 index 0000000..6371404 --- /dev/null +++ b/gerbview/rs274x.cpp @@ -0,0 +1,1064 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2007-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file rs274x.cpp + */ + +#include <fctsys.h> +#include <common.h> +#include <macros.h> +#include <base_units.h> + +#include <gerbview.h> +#include <class_GERBER.h> +#include <class_X2_gerber_attributes.h> + +extern int ReadInt( char*& text, bool aSkipSeparator = true ); +extern double ReadDouble( char*& text, bool aSkipSeparator = true ); +extern bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file ); + + +#define CODE( x, y ) ( ( (x) << 8 ) + (y) ) + +// See rs274xrevd_e.pdf, table 1: RS-274X parameters order of entry +// in gerber files, when a coordinate is given (like X78Y600 or I0J80): +// Y and Y are logical coordinates +// A and B are plotter coordiantes +// Usually A = X, B = Y +// But we can have A = Y, B = X and/or offset, mirror, scale; +// Also: +// Image is what you must plot (the entire data of the file). +// Layer is just a set of data blocks with their parameters. An image can have more than one +// layer so a gerber layer is not like a board layer or the graphic layers used in GerbView +// to show a file. +enum RS274X_PARAMETERS { + // Directive parameters: single usage recommended + // Must be at the beginning of the file + AXIS_SELECT = CODE( 'A', 'S' ), // Default: A=X, B=Y + FORMAT_STATEMENT = CODE( 'F', 'S' ), // no default: this command must exists + MIRROR_IMAGE = CODE( 'M', 'I' ), // Default: mo mirror + MODE_OF_UNITS = CODE( 'M', 'O' ), // Default: inch + INCH = CODE( 'I', 'N' ), + MILLIMETER = CODE( 'M', 'M' ), + OFFSET = CODE( 'O', 'F' ), // Default: A = 0, B = 0 + SCALE_FACTOR = CODE( 'S', 'F' ), // Default: A = 1.0, B = 1.0 + + // Image parameters: + // commands used only once at the beginning of the file + IMAGE_JUSTIFY = CODE( 'I', 'J' ), // Default: no justification + IMAGE_NAME = CODE( 'I', 'N' ), // Default: void + IMAGE_OFFSET = CODE( 'I', 'O' ), // Default: A = 0, B = 0 + IMAGE_POLARITY = CODE( 'I', 'P' ), // Default: Positive + IMAGE_ROTATION = CODE( 'I', 'R' ), // Default: 0 + PLOTTER_FILM = CODE( 'P', 'M' ), + + // Aperture parameters: + // Usually for the whole file + AP_DEFINITION = CODE( 'A', 'D' ), + AP_MACRO = CODE( 'A', 'M' ), + + // X2 extention attribute commands + // Mainly are found standard attributes and user attributes + // standard attributes commands are: + // TF (file attribute) + // TA (aperture attribute) and TD (delete aperture attribute) + FILE_ATTRIBUTE = CODE( 'T', 'F' ), + + // Layer specific parameters + // May be used singly or may be layer specfic + // theses parameters are at the beginning of the file or layer + // and reset some layer parameters (like interpolation) + LAYER_NAME = CODE( 'L', 'N' ), // Default: Positive + LAYER_POLARITY = CODE( 'L', 'P' ), + KNOCKOUT = CODE( 'K', 'O' ), // Default: off + STEP_AND_REPEAT = CODE( 'S', 'R' ), // Default: A = 1, B = 1 + ROTATE = CODE( 'R', 'O' ), // Default: 0 + + // Miscellaneous parameters: + INCLUDE_FILE = CODE( 'I', 'F' ) +}; + + +/** + * Function ReadXCommand + * reads in two bytes of data and assembles them into an int with the first + * byte in the sequence put into the most significant part of a 16 bit value + * and the second byte put into the least significant part of the 16 bit value. + * @param text A reference to a pointer to read bytes from and to advance as + * they are read. + * @return int - with 16 bits of data in the ls bits, upper bits zeroed. + */ +static int ReadXCommand( char*& text ) +{ + int result; + + if( text && *text ) + result = *text++ << 8; + else + return -1; + + if( text && *text ) + result += *text++; + else + return -1; + + return result; +} + + +bool GERBER_IMAGE::ReadRS274XCommand( char buff[GERBER_BUFZ], char*& text ) +{ + bool ok = true; + int code_command; + + text++; + + for( ; ; ) + { + while( *text ) + { + switch( *text ) + { + case '%': // end of command + text++; + m_CommandState = CMD_IDLE; + goto exit; // success completion + + case ' ': + case '\r': + case '\n': + text++; + break; + + case '*': + text++; + break; + + default: + code_command = ReadXCommand( text ); + ok = ExecuteRS274XCommand( code_command, buff, text ); + if( !ok ) + goto exit; + break; + } + } + + // end of current line, read another one. + if( fgets( buff, GERBER_BUFZ, m_Current_File ) == NULL ) + { + // end of file + ok = false; + break; + } + + text = buff; + } + +exit: + return ok; +} + + +bool GERBER_IMAGE::ExecuteRS274XCommand( int command, + char buff[GERBER_BUFZ], + char*& text ) +{ + int code; + int seq_len; // not used, just provided + int seq_char; + bool ok = true; + char line[GERBER_BUFZ]; + wxString msg; + double fcoord; + bool x_fmt_known = false; + bool y_fmt_known = false; + + // conv_scale = scaling factor from inch to Internal Unit + double conv_scale = IU_PER_MILS * 1000; + if( m_GerbMetric ) + conv_scale /= 25.4; + +// DBG( printf( "%22s: Command <%c%c>\n", __func__, (command >> 8) & 0xFF, command & 0xFF ); ) + + switch( command ) + { + case FORMAT_STATEMENT: + seq_len = 2; + + while( *text != '*' ) + { + switch( *text ) + { + case ' ': + text++; + break; + + case 'L': // No Leading 0 + m_DecimalFormat = false; + m_NoTrailingZeros = false; + text++; + break; + + case 'T': // No trailing 0 + m_DecimalFormat = false; + m_NoTrailingZeros = true; + text++; + break; + + case 'A': // Absolute coord + m_Relative = false; + text++; + break; + + case 'I': // Relative coord + m_Relative = true; + text++; + break; + + case 'G': + case 'N': // Sequence code (followed by one digit: the sequence len) + // (sometimes found before the X,Y sequence) + // Obscure option + text++; + seq_char = *text++; + if( (seq_char >= '0') && (seq_char <= '9') ) + seq_len = seq_char - '0'; + break; + + case 'D': + case 'M': // Sequence code (followed by one digit: the sequence len) + // (sometimes found after the X,Y sequence) + // Obscure option + code = *text++; + if( ( *text >= '0' ) && ( *text<= '9' ) ) + text++; // skip the digit + else if( code == 'D' ) + // Decimal format: sometimes found, but not really documented + m_DecimalFormat = true; + break; + + case 'X': + case 'Y': + { + code = *(text++); + char ctmp = *(text++) - '0'; + if( code == 'X' ) + { + x_fmt_known = true; + // number of digits after the decimal point (0 to 7 allowed) + m_FmtScale.x = *text - '0'; + m_FmtLen.x = ctmp + m_FmtScale.x; + + // m_FmtScale is 0 to 7 + // (Old Gerber specification was 0 to 6) + if( m_FmtScale.x < 0 ) + m_FmtScale.x = 0; + if( m_FmtScale.x > 7 ) + m_FmtScale.x = 7; + } + else + { + y_fmt_known = true; + m_FmtScale.y = *text - '0'; + m_FmtLen.y = ctmp + m_FmtScale.y; + if( m_FmtScale.y < 0 ) + m_FmtScale.y = 0; + if( m_FmtScale.y > 7 ) + m_FmtScale.y = 7; + } + text++; + } + break; + + case '*': + break; + + default: + msg.Printf( wxT( "Unknown id (%c) in FS command" ), + *text ); + ReportMessage( msg ); + GetEndOfBlock( buff, text, m_Current_File ); + ok = false; + break; + } + } + if( !x_fmt_known || !y_fmt_known ) + ReportMessage( wxT( "RS274X: Format Statement (FS) without X or Y format" ) ); + + break; + + case AXIS_SELECT: // command ASAXBY*% or %ASAYBX*% + m_SwapAxis = false; + if( strnicmp( text, "AYBX", 4 ) == 0 ) + m_SwapAxis = true; + break; + + case MIRROR_IMAGE: // command %MIA0B0*%, %MIA0B1*%, %MIA1B0*%, %MIA1B1*% + m_MirrorA = m_MirrorB = 0; + while( *text && *text != '*' ) + { + switch( *text ) + { + case 'A': // Mirror A axis ? + text++; + if( *text == '1' ) + m_MirrorA = true; + break; + + case 'B': // Mirror B axis ? + text++; + if( *text == '1' ) + m_MirrorB = true; + break; + + default: + text++; + break; + } + } + break; + + case MODE_OF_UNITS: + code = ReadXCommand( text ); + if( code == INCH ) + m_GerbMetric = false; + else if( code == MILLIMETER ) + m_GerbMetric = true; + conv_scale = m_GerbMetric ? IU_PER_MILS / 25.4 : IU_PER_MILS; + break; + + case FILE_ATTRIBUTE: // Command %TF ... + m_IsX2_file = true; + { + X2_ATTRIBUTE dummy; + dummy.ParseAttribCmd( m_Current_File, buff, GERBER_BUFZ, text ); + if( dummy.IsFileFunction() ) + { + delete m_FileFunction; + m_FileFunction = new X2_ATTRIBUTE_FILEFUNCTION( dummy ); + } + else if( dummy.IsFileMD5() ) + { + m_MD5_value = dummy.GetPrm( 1 ); + } + else if( dummy.IsFilePart() ) + { + m_PartString = dummy.GetPrm( 1 ); + } + } + break; + + case OFFSET: // command: OFAnnBnn (nn = float number) = layer Offset + m_Offset.x = m_Offset.y = 0; + while( *text != '*' ) + { + switch( *text ) + { + case 'A': // A axis offset in current unit (inch or mm) + text++; + fcoord = ReadDouble( text ); + m_Offset.x = KiROUND( fcoord * conv_scale ); + break; + + case 'B': // B axis offset in current unit (inch or mm) + text++; + fcoord = ReadDouble( text ); + m_Offset.y = KiROUND( fcoord * conv_scale ); + break; + } + } + break; + + case SCALE_FACTOR: + m_Scale.x = m_Scale.y = 1.0; + while( *text != '*' ) + { + switch( *text ) + { + case 'A': // A axis scale + text++; + m_Scale.x = ReadDouble( text ); + break; + + case 'B': // B axis scale + text++; + m_Scale.y = ReadDouble( text ); + break; + } + } + break; + + case IMAGE_OFFSET: // command: IOAnnBnn (nn = float number) = Image Offset + m_ImageOffset.x = m_ImageOffset.y = 0; + while( *text != '*' ) + { + switch( *text ) + { + case 'A': // A axis offset in current unit (inch or mm) + text++; + fcoord = ReadDouble( text ); + m_ImageOffset.x = KiROUND( fcoord * conv_scale ); + break; + + case 'B': // B axis offset in current unit (inch or mm) + text++; + fcoord = ReadDouble( text ); + m_ImageOffset.y = KiROUND( fcoord * conv_scale ); + break; + } + } + break; + + case IMAGE_ROTATION: // command IR0* or IR90* or IR180* or IR270* + if( strnicmp( text, "0*", 2 ) == 0 ) + m_ImageRotation = 0; + else if( strnicmp( text, "90*", 3 ) == 0 ) + m_ImageRotation = 90; + else if( strnicmp( text, "180*", 4 ) == 0 ) + m_ImageRotation = 180; + else if( strnicmp( text, "270*", 4 ) == 0 ) + m_ImageRotation = 270; + else + ReportMessage( _( "RS274X: Command \"IR\" rotation value not allowed" ) ); + break; + + case STEP_AND_REPEAT: // command SR, like %SRX3Y2I5.0J2*% + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer + GetLayerParams().m_StepForRepeat.x = 0.0; + GetLayerParams().m_StepForRepeat.x = 0.0; // offset for Step and Repeat command + GetLayerParams().m_XRepeatCount = 1; + GetLayerParams().m_YRepeatCount = 1; // The repeat count + GetLayerParams().m_StepForRepeatMetric = m_GerbMetric; // the step units + while( *text && *text != '*' ) + { + switch( *text ) + { + case 'I': // X axis offset + text++; + GetLayerParams().m_StepForRepeat.x = ReadDouble( text ); + break; + + case 'J': // Y axis offset + text++; + GetLayerParams().m_StepForRepeat.y = ReadDouble( text ); + break; + + case 'X': // X axis repeat count + text++; + GetLayerParams().m_XRepeatCount = ReadInt( text ); + break; + + case 'Y': // Y axis offset + text++; + GetLayerParams().m_YRepeatCount = ReadInt( text ); + break; + default: + text++; + break; + } + } + break; + + case IMAGE_JUSTIFY: // Command IJAnBn* + m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false) + m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false) + m_ImageJustifyOffset = wxPoint(0,0); // Image Justify Offset on XY axis (default = 0,0) + while( *text && *text != '*' ) + { + // IJ command is (for A or B axis) AC or AL or A<coordinate> + switch( *text ) + { + case 'A': // A axis justify + text++; + if( *text == 'C' ) + { + m_ImageJustifyXCenter = true; + text++; + } + else if( *text == 'L' ) + { + m_ImageJustifyXCenter = true; + text++; + } + else m_ImageJustifyOffset.x = KiROUND( ReadDouble( text ) * conv_scale); + break; + + case 'B': // B axis justify + text++; + if( *text == 'C' ) + { + m_ImageJustifyYCenter = true; + text++; + } + else if( *text == 'L' ) + { + m_ImageJustifyYCenter = true; + text++; + } + else m_ImageJustifyOffset.y = KiROUND( ReadDouble( text ) * conv_scale); + break; + default: + text++; + break; + } + } + if( m_ImageJustifyXCenter ) + m_ImageJustifyOffset.x = 0; + if( m_ImageJustifyYCenter ) + m_ImageJustifyOffset.y = 0; + break; + + case KNOCKOUT: + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer + msg = _( "RS274X: Command KNOCKOUT ignored by GerbView" ) ; + ReportMessage( msg ); + break; + + case PLOTTER_FILM: // Command PF <string> + // This is an info about film that must be used to plot this file + // Has no meaning here. We just display this string + msg = wxT( "Plotter Film info:<br>" ); + while( *text != '*' ) + { + msg.Append( *text++ ); + } + ReportMessage( msg ); + break; + + case ROTATE: // Layer rotation: command like %RO45*% + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer + m_LocalRotation =ReadDouble( text ); // Store layer rotation in degrees + break; + + case IMAGE_NAME: + m_ImageName.Empty(); + while( *text != '*' ) + { + m_ImageName.Append( *text++ ); + } + + break; + + case LAYER_NAME: + m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Start a new Gerber layer + GetLayerParams( ).m_LayerName.Empty(); + while( *text != '*' ) + { + GetLayerParams( ).m_LayerName.Append( *text++ ); + } + + break; + + case IMAGE_POLARITY: + if( strnicmp( text, "NEG", 3 ) == 0 ) + m_ImageNegative = true; + else + m_ImageNegative = false; + DBG( printf( "%22s: IMAGE_POLARITY m_ImageNegative=%s\n", __func__, + m_ImageNegative ? "true" : "false" ); ) + break; + + case LAYER_POLARITY: + if( *text == 'C' ) + GetLayerParams().m_LayerNegative = true; + + else + GetLayerParams().m_LayerNegative = false; + DBG( printf( "%22s: LAYER_POLARITY m_LayerNegative=%s\n", __func__, + GetLayerParams().m_LayerNegative ? "true" : "false" ); ) + break; + + case INCLUDE_FILE: + if( m_FilesPtr >= INCLUDE_FILES_CNT_MAX ) + { + ok = false; + ReportMessage( _( "Too many include files!!" ) ); + break; + } + + strncpy( line, text, sizeof(line)-1 ); + line[sizeof(line)-1] = '\0'; + + strtok( line, "*%%\n\r" ); + m_FilesList[m_FilesPtr] = m_Current_File; + + m_Current_File = fopen( line, "rt" ); + if( m_Current_File == 0 ) + { + msg.Printf( wxT( "include file <%s> not found." ), line ); + ReportMessage( msg ); + ok = false; + m_Current_File = m_FilesList[m_FilesPtr]; + break; + } + m_FilesPtr++; + break; + + case AP_MACRO: // lines like %AMMYMACRO* + // 5,1,8,0,0,1.08239X$1,22.5* + // % + /*ok = */ReadApertureMacro( buff, text, m_Current_File ); + break; + + case AP_DEFINITION: + + /* input example: %ADD30R,0.081800X0.101500*% + * Aperture definition has 4 options: C, R, O, P + * (Circle, Rect, Oval, regular Polygon) + * and shapes can have a hole (round or rectangular). + * All optional parameters values start by X + * at this point, text points to 2nd 'D' + */ + if( *text++ != 'D' ) + { + ok = false; + break; + } + + m_Has_DCode = true; + + code = ReadInt( text ); + + D_CODE* dcode; + dcode = GetDCODE( code ); + if( dcode == NULL ) + break; + + // at this point, text points to character after the ADD<num>, + // i.e. R in example above. If text[0] is one of the usual + // apertures: (C,R,O,P), there is a comma after it. + if( text[1] == ',' ) + { + char stdAperture = *text; + + text += 2; // skip "C," for example + + dcode->m_Size.x = KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_Size.y = dcode->m_Size.x; + + switch( stdAperture ) // Aperture desceiption has optional parameters. Read them + { + case 'C': // Circle + dcode->m_Shape = APT_CIRCLE; + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.x = dcode->m_Drill.y = + KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_DrillShape = APT_DEF_ROUND_HOLE; + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.y = + KiROUND( ReadDouble( text ) * conv_scale ); + + dcode->m_DrillShape = APT_DEF_RECT_HOLE; + } + dcode->m_Defined = true; + break; + + case 'O': // oval + case 'R': // rect + dcode->m_Shape = (stdAperture == 'O') ? APT_OVAL : APT_RECT; + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Size.y = + KiROUND( ReadDouble( text ) * conv_scale ); + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.x = KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_Drill.y = dcode->m_Drill.x; + dcode->m_DrillShape = APT_DEF_ROUND_HOLE; + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.y = + KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_DrillShape = APT_DEF_RECT_HOLE; + } + dcode->m_Defined = true; + break; + + case 'P': + + /* Regular polygon: a command line like %ADD12P,0.040X10X25X0.025X0.025X0.0150*% + * params are: <diameter>, X<edge count>, X<Rotation>, X<X hole dim>, X<Y hole dim> + */ + dcode->m_Shape = APT_POLYGON; + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_EdgesCount = ReadInt( text ); + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Rotation = ReadDouble( text ); + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.x = KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_Drill.y = dcode->m_Drill.x = + dcode->m_DrillShape = APT_DEF_ROUND_HOLE; + } + + while( *text == ' ' ) + text++; + + if( *text == 'X' ) + { + text++; + dcode->m_Drill.y = KiROUND( ReadDouble( text ) * conv_scale ); + dcode->m_DrillShape = APT_DEF_RECT_HOLE; + } + dcode->m_Defined = true; + break; + } + } + else // text[0] starts an aperture macro name + { + APERTURE_MACRO am_lookup; + + while( *text && *text != '*' && *text != ',' ) + am_lookup.name.Append( *text++ ); + + // When an aperture definition is like %AMLINE2* 22,1,$1,$2,0,0,-45* + // the ADDxx<MACRO_NAME> command has parameters, like %ADD14LINE2,0.8X0.5*% + if( *text == ',' ) + { // Read aperture macro parameters and store them + text++; // text points the first parameter + while( *text && *text != '*' ) + { + double param = ReadDouble( text ); + dcode->AppendParam( param ); + while( isspace( *text ) ) text++; + if( *text == 'X' ) + ++text; + } + } + + // lookup the aperture macro here. + APERTURE_MACRO* pam = FindApertureMacro( am_lookup ); + if( !pam ) + { + msg.Printf( wxT( "RS274X: aperture macro %s not found\n" ), + TO_UTF8( am_lookup.name ) ); + ReportMessage( msg ); + ok = false; + break; + } + + dcode->m_Shape = APT_MACRO; + dcode->SetMacro( (APERTURE_MACRO*) pam ); + } + break; + + default: + ok = false; + break; + } + + (void) seq_len; // quiet g++, or delete the unused variable. + + ok = GetEndOfBlock( buff, text, m_Current_File ); + + return ok; +} + + +bool GetEndOfBlock( char buff[GERBER_BUFZ], char*& text, FILE* gerber_file ) +{ + for( ; ; ) + { + while( (text < buff + GERBER_BUFZ) && *text ) + { + if( *text == '*' ) + return true; + + if( *text == '%' ) + return true; + + text++; + } + + if( fgets( buff, GERBER_BUFZ, gerber_file ) == NULL ) + break; + + text = buff; + } + + return false; +} + + +/** + * Function GetNextLine + * test for an end of line + * if an end of line is found: + * read a new line + * @param aBuff = buffer (size = GERBER_BUFZ) to fill with a new line + * @param aText = pointer to the last useful char in aBuff + * on return: points the beginning of the next line. + * @param aFile = the opened GERBER file to read + * @return a pointer to the beginning of the next line or NULL if end of file +*/ +static char* GetNextLine( char aBuff[GERBER_BUFZ], char* aText, FILE* aFile ) +{ + for( ; ; ) + { + switch (*aText ) + { + case ' ': // skip blanks + case '\n': + case '\r': // Skip line terminators + ++aText; + break; + + case 0: // End of text found in aBuff: Read a new string + if( fgets( aBuff, GERBER_BUFZ, aFile ) == NULL ) + return NULL; + aText = aBuff; + return aText; + + default: + return aText; + } + } + return aText; +} + + +bool GERBER_IMAGE::ReadApertureMacro( char buff[GERBER_BUFZ], + char*& text, + FILE* gerber_file ) +{ + wxString msg; + APERTURE_MACRO am; + + // read macro name + while( *text ) + { + if( *text == '*' ) + { + ++text; + break; + } + + am.name.Append( *text++ ); + } + + // Read aperture macro parameters + for( ; ; ) + { + if( *text == '*' ) + ++text; + + text = GetNextLine( buff, text, gerber_file ); // Get next line + if( text == NULL ) // End of File + return false; + + // text points the beginning of a new line. + + // Test for the last line in aperture macro lis: + // last line is % or *% sometime found. + if( *text == '*' ) + ++text; + if( *text == '%' ) + break; // exit with text still pointing at % + + int paramCount = 0; + int primitive_type = AMP_UNKNOWN; + // Test for a valid symbol at the beginning of a description: + // it can be: a parameter declaration like $1=$2/4 + // or a digit (macro primitive selection) + // all other symbols are illegal. + if( *text == '$' ) // local parameter declaration, inside the aperture macro + { + am.m_localparamStack.push_back( AM_PARAM() ); + AM_PARAM& param = am.m_localparamStack.back(); + text = GetNextLine( buff, text, gerber_file ); + if( text == NULL) // End of File + return false; + param.ReadParam( text ); + continue; + } + else if( !isdigit(*text) ) // Ill. symbol + { + msg.Printf( wxT( "RS274X: Aperture Macro \"%s\": ill. symbol, line: \"%s\"" ), + GetChars( am.name ), GetChars( FROM_UTF8( buff ) ) ); + ReportMessage( msg ); + primitive_type = AMP_COMMENT; + } + else + primitive_type = ReadInt( text ); + + switch( primitive_type ) + { + case AMP_COMMENT: // lines starting by 0 are a comment + paramCount = 0; + // Skip comment + while( *text && (*text != '*') ) + text++; + break; + + case AMP_CIRCLE: + paramCount = 4; + break; + + case AMP_LINE2: + case AMP_LINE20: + paramCount = 7; + break; + + case AMP_LINE_CENTER: + case AMP_LINE_LOWER_LEFT: + paramCount = 6; + break; + + case AMP_EOF: + paramCount = 0; + break; + + case AMP_OUTLINE: + paramCount = 4; + break; + + case AMP_POLYGON: + paramCount = 6; + break; + + case AMP_MOIRE: + paramCount = 9; + break; + + case AMP_THERMAL: + paramCount = 6; + break; + + default: + // @todo, there needs to be a way of reporting the line number + msg.Printf( wxT( "RS274X: Aperture Macro \"%s\": Invalid primitive id code %d, line: \"%s\"" ), + GetChars( am.name ), primitive_type, GetChars( FROM_UTF8( buff ) ) ); + ReportMessage( msg ); + return false; + } + + AM_PRIMITIVE prim( m_GerbMetric ); + prim.primitive_id = (AM_PRIMITIVE_ID) primitive_type; + int i; + + for( i = 0; i < paramCount && *text && *text != '*'; ++i ) + { + prim.params.push_back( AM_PARAM() ); + + AM_PARAM& param = prim.params.back(); + + text = GetNextLine( buff, text, gerber_file ); + + if( text == NULL) // End of File + return false; + + param.ReadParam( text ); + } + + if( i < paramCount ) + { + // maybe some day we can throw an exception and track a line number + msg.Printf( wxT( "RS274X: read macro descr type %d: read %d parameters, insufficient parameters\n" ), + prim.primitive_id, i ); + ReportMessage( msg ); + + } + // there are more parameters to read if this is an AMP_OUTLINE + if( prim.primitive_id == AMP_OUTLINE ) + { + // so far we have read [0]:exposure, [1]:#points, [2]:X start, [3]: Y start + // Now read all the points, plus trailing rotation in degrees. + + // params[1] is a count of polygon points, so it must be given + // in advance, i.e. be immediate. + wxASSERT( prim.params[1].IsImmediate() ); + + paramCount = (int) prim.params[1].GetValue( 0 ) * 2 + 1; + + for( int i = 0; i < paramCount && *text != '*'; ++i ) + { + prim.params.push_back( AM_PARAM() ); + + AM_PARAM& param = prim.params.back(); + + text = GetNextLine( buff, text, gerber_file ); + + if( text == NULL ) // End of File + return false; + + param.ReadParam( text ); + } + } + + am.primitives.push_back( prim ); + } + + m_aperture_macros.insert( am ); + + return true; +} + diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp new file mode 100644 index 0000000..4fa8938 --- /dev/null +++ b/gerbview/select_layers_to_pcb.cpp @@ -0,0 +1,428 @@ +/** + * @file select_layers_to_pcb.cpp + * @brief Dialog to choose equivalence between gerber layers and pcb layers + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <fctsys.h> +#include <kiface_i.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <gerbview_id.h> +#include <class_GERBER.h> + +#include <select_layers_to_pcb.h> + +// Imported function +extern const wxString GetPCBDefaultLayerName( LAYER_NUM aLayerNumber ); + +enum swap_layer_id { + ID_LAYERS_MAP_DIALOG = ID_GERBER_END_LIST, + ID_BUTTON_0, + ID_TEXT_0 = ID_BUTTON_0 + GERBER_DRAWLAYERS_COUNT +}; + + +/* + * This dialog shows the gerber files loaded, and allows user to choose: + * what gerber file and what board layer are used + * the number of copper layers + */ + +int LAYERS_MAP_DIALOG::m_exportBoardCopperLayersCount = 2; + + +BEGIN_EVENT_TABLE( LAYERS_MAP_DIALOG, LAYERS_MAP_DIALOG_BASE ) + EVT_COMMAND_RANGE( ID_BUTTON_0, ID_BUTTON_0 + GERBER_DRAWLAYERS_COUNT-1, + wxEVT_COMMAND_BUTTON_CLICKED, + LAYERS_MAP_DIALOG::OnSelectLayer ) +END_EVENT_TABLE() + + +LAYERS_MAP_DIALOG::LAYERS_MAP_DIALOG( GERBVIEW_FRAME* parent ) : + LAYERS_MAP_DIALOG_BASE( parent ) +{ + m_Parent = parent; + initDialog(); + + // Resize the dialog + Layout(); + GetSizer()->SetSizeHints( this ); + Centre(); +} + + +void LAYERS_MAP_DIALOG::initDialog() +{ + wxStaticText* label; + wxStaticText* text; + int item_ID; + wxString msg; + wxSize goodSize; + + m_flexRightColumnBoxSizer = NULL; + + // Experimentation has shown that buttons in the Windows version can be 20 + // pixels wide and 20 pixels high, but that they need to be 26 pixels wide + // and 26 pixels high in the Linux version. (And although the dimensions + // of those buttons could be set to 26 pixels wide and 26 pixels high in + // both of those versions, that would result in a dialog box which would + // be excessively high in the Windows version.) +#ifdef __WINDOWS__ + int w = 20; + int h = 20; +#else + int w = 26; + int h = 26; +#endif + + // As currently implemented, the dimensions of the buttons in the Mac + // version are also 26 pixels wide and 26 pixels high. If appropriate, + // the above code should be modified as required in the event that those + // buttons should be some other size in that version. + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + // Specify the default value for each member of these arrays. + m_buttonTable[ii] = -1; + m_layersLookUpTable[ii] = UNSELECTED_LAYER; + } + + // Ensure we have: + // at least 2 copper layers and less than max pacb copper layers count + // and even layers count because a board *must* have even layers count + normalizeBrdLayersCount(); + + int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1; + m_comboCopperLayersCount->SetSelection( idx ); + + LAYER_NUM pcb_layer_num = 0; + m_gerberActiveLayersCount = 0; + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + if( g_GERBER_List.GetGbrImage( ii ) == NULL ) + break; + + if( (pcb_layer_num == m_exportBoardCopperLayersCount - 1) + && (m_exportBoardCopperLayersCount > 1) ) + pcb_layer_num = F_Cu; + + m_buttonTable[m_gerberActiveLayersCount] = ii; + m_layersLookUpTable[ii] = pcb_layer_num; + m_gerberActiveLayersCount++; + ++pcb_layer_num; + } + + if( m_gerberActiveLayersCount <= GERBER_DRAWLAYERS_COUNT/2 ) // Only one list is enough + { + m_staticlineSep->Hide(); + } + else // Add the second list of gerber files + { + m_flexRightColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 ); + for( int ii = 0; ii < 4; ii++ ) + m_flexRightColumnBoxSizer->AddGrowableCol( ii ); + m_flexRightColumnBoxSizer->SetFlexibleDirection( wxBOTH ); + m_flexRightColumnBoxSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + sbSizerLayersTable->Add( m_flexRightColumnBoxSizer, 1, wxEXPAND, 5 ); + } + + wxFlexGridSizer* flexColumnBoxSizer = m_flexLeftColumnBoxSizer; + for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ ) + { + // Each Gerber layer has an associated static text string (to + // identify that layer), a button (for invoking a child dialog + // box to change which Pcbnew layer that the Gerber layer is + // mapped to), and a second static text string (to depict which + // Pcbnew layer that the Gerber layer has been mapped to). Each + // of those items are placed into the left hand column, middle + // column, and right hand column (respectively) of the Flexgrid + // sizer, and the color of the second text string is set to + // fuchsia or blue (to respectively indicate whether the Gerber + // layer has been mapped to a Pcbnew layer or is not being + // exported at all). (Experimentation has shown that if a text + // control is used to depict which Pcbnew layer that each Gerber + // layer is mapped to (instead of a static text string), then + // those controls do not behave in a fully satisfactory manner + // in the Linux version. Even when the read-only attribute is + // specified for all of those controls, they can still be selected + // when the arrow keys or Tab key is used to step through all of + // the controls within the dialog box, and directives to set the + // foreground color of the text of each such control to blue (to + // indicate that the text is of a read-only nature) are disregarded. + // Specify a FlexGrid sizer with an appropriate number of rows + // and three columns. If nb_items < 16, then the number of rows + // is nb_items; otherwise, the number of rows is 16 (with two + // separate columns of controls being used if nb_items > 16). + + if( ii == GERBER_DRAWLAYERS_COUNT/2 ) + flexColumnBoxSizer = m_flexRightColumnBoxSizer; + + // Provide a text string to identify the Gerber layer + msg.Printf( _( "Layer %d" ), m_buttonTable[ii] + 1 ); + + label = new wxStaticText( this, wxID_STATIC, msg, wxDefaultPosition, + wxDefaultSize, wxALIGN_RIGHT ); + flexColumnBoxSizer->Add( label, 0, + wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | + wxRIGHT | wxLEFT, 5 ); + + /* Add file name and extension without path. */ + wxFileName fn( g_GERBER_List.GetGbrImage( ii )->m_FileName ); + label = new wxStaticText( this, wxID_STATIC, fn.GetFullName(), + wxDefaultPosition, wxDefaultSize ); + flexColumnBoxSizer->Add( label, 0, + wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | + wxRIGHT | wxLEFT, 5 ); + + // Provide a button for this layer (which will invoke a child dialog box) + item_ID = ID_BUTTON_0 + ii; + wxButton * Button = new wxButton( this, item_ID, wxT( "..." ), + wxDefaultPosition, wxSize( w, h ), 0 ); + + flexColumnBoxSizer->Add( Button, 0, + wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL ); + + // Provide another text string to specify which Pcbnew layer that this + // Gerber layer is initially mapped to, and set the initial text to + // specify the appropriate Pcbnew layer, and set the foreground color + // of the text to fuchsia (to indicate that the layer is being exported). + item_ID = ID_TEXT_0 + ii; + + // When the first of these text strings is being added, determine what + // size is necessary to to be able to display any possible string + // without it being truncated. Then specify that size as the minimum + // size for all of these text strings. (If this minimum size is not + // determined in this fashion, then it is possible for the display of + // one or more of these strings to be truncated after different Pcbnew + // layers are selected.) + if( ii == 0 ) + { + msg = _( "Do not export" ); + text = new wxStaticText( this, item_ID, msg, wxDefaultPosition, + wxDefaultSize, 0 ); + goodSize = text->GetSize(); + + for( LAYER_NUM jj = 0; jj < GERBER_DRAWLAYERS_COUNT; ++jj ) + { + text->SetLabel( GetPCBDefaultLayerName( jj ) ); + if( goodSize.x < text->GetSize().x ) + goodSize.x = text->GetSize().x; + } + + msg = GetPCBDefaultLayerName( m_layersLookUpTable[m_buttonTable[ii]] ); + text->SetLabel( msg ); + } + else + { + msg = GetPCBDefaultLayerName( m_layersLookUpTable[m_buttonTable[ii]] ); + text = new wxStaticText( this, item_ID, msg, wxDefaultPosition, + wxDefaultSize, 0 ); + } + text->SetMinSize( goodSize ); + flexColumnBoxSizer->Add( text, 1, + wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, + 5 ); + + m_layersList[ii] = text; + } +} + +/* Ensure m_exportBoardCopperLayersCount = 2 to BOARD_COPPER_LAYERS_MAX_COUNT + * and it is an even value because Boards have always an even layer count + */ +void LAYERS_MAP_DIALOG::normalizeBrdLayersCount() +{ + if( ( m_exportBoardCopperLayersCount & 1 ) ) + m_exportBoardCopperLayersCount++; + + if( m_exportBoardCopperLayersCount > GERBER_DRAWLAYERS_COUNT ) + m_exportBoardCopperLayersCount = GERBER_DRAWLAYERS_COUNT; + + if( m_exportBoardCopperLayersCount < 2 ) + m_exportBoardCopperLayersCount = 2; + +} + +/* + * Called when user change the current board copper layers count + */ +void LAYERS_MAP_DIALOG::OnBrdLayersCountSelection( wxCommandEvent& event ) +{ + int id = event.GetSelection(); + m_exportBoardCopperLayersCount = (id+1) * 2; +} + +/* + * reset pcb layers selection to the default value + */ +void LAYERS_MAP_DIALOG::OnResetClick( wxCommandEvent& event ) +{ + wxString msg; + int ii; + LAYER_NUM layer; + for( ii = 0, layer = 0; ii < m_gerberActiveLayersCount; ii++, ++layer ) + { + if( (layer == m_exportBoardCopperLayersCount - 1) + && (m_exportBoardCopperLayersCount > 1) ) + layer = F_Cu; + m_layersLookUpTable[ii] = layer; + msg = GetPCBDefaultLayerName( layer ); + m_layersList[ii]->SetLabel( msg ); + m_layersList[ii]->SetForegroundColour( wxNullColour ); + m_buttonTable[ii] = ii; + } +} + + +/* Stores the current layers selection in config + */ +void LAYERS_MAP_DIALOG::OnStoreSetup( wxCommandEvent& event ) +{ + wxConfigBase* config = Kiface().KifaceSettings(); + config->Write( wxT("BrdLayersCount"), m_exportBoardCopperLayersCount ); + + wxString key; + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + key.Printf( wxT("GbrLyr%dToPcb"), ii ); + config->Write( key, m_layersLookUpTable[ii] ); + } +} + +void LAYERS_MAP_DIALOG::OnGetSetup( wxCommandEvent& event ) +{ + wxConfigBase* config = Kiface().KifaceSettings(); + + config->Read( wxT("BrdLayersCount"), &m_exportBoardCopperLayersCount ); + normalizeBrdLayersCount(); + + int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1; + m_comboCopperLayersCount->SetSelection( idx ); + + wxString key; + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + key.Printf( wxT("GbrLyr%dToPcb"), ii ); + int ilayer; + config->Read( key, &ilayer); + m_layersLookUpTable[ii] = ilayer; + } + + for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ ) + { + LAYER_NUM layer = m_layersLookUpTable[ii]; + if( layer == UNSELECTED_LAYER ) + { + m_layersList[ii]->SetLabel( _( "Do not export" ) ); + m_layersList[ii]->SetForegroundColour( *wxBLUE ); + } + else + { + m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( layer ) ); + m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) ); + } + } +} + +void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event ) +{ + int ii; + + ii = event.GetId() - ID_BUTTON_0; + + if( (ii < 0) || (ii >= GERBER_DRAWLAYERS_COUNT) ) + { + wxFAIL_MSG( wxT("Bad layer id") ); + return; + } + + LAYER_NUM jj = m_layersLookUpTable[m_buttonTable[ii]]; + + if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) ) + jj = B_Cu; // (Defaults to "Copper" layer.) + + jj = m_Parent->SelectPCBLayer( jj, m_exportBoardCopperLayersCount, true ); + + if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) ) + return; + + if( jj != m_layersLookUpTable[m_buttonTable[ii]] ) + { + m_layersLookUpTable[m_buttonTable[ii]] = jj; + + if( jj == UNSELECTED_LAYER ) + { + m_layersList[ii]->SetLabel( _( "Do not export" ) ); + + // Change the text color to blue (to highlight + // that this layer is *not* being exported) + m_layersList[ii]->SetForegroundColour( *wxBLUE ); + } + else + { + m_layersList[ii]->SetLabel( GetPCBDefaultLayerName( jj ) ); + + // Change the text color to fuchsia (to highlight + // that this layer *is* being exported) + m_layersList[ii]->SetForegroundColour( wxColour( 255, 0, 128 ) ); + } + } +} + + +void LAYERS_MAP_DIALOG::OnCancelClick( wxCommandEvent& event ) +{ + EndModal( wxID_CANCEL ); +} + + +void LAYERS_MAP_DIALOG::OnOkClick( wxCommandEvent& event ) +{ + /* Make some test about copper layers: + * Board must have enough copper layers to handle selected internal layers + */ + normalizeBrdLayersCount(); + + int inner_layer_max = 0; + for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii ) + { + if( m_layersLookUpTable[ii] < F_Cu ) + { + if( m_layersLookUpTable[ii ] > inner_layer_max ) + inner_layer_max = m_layersLookUpTable[ii]; + } + } + + // inner_layer_max must be less than (or equal to) the number of + // internal copper layers + // internal copper layers = m_exportBoardCopperLayersCount-2 + if( inner_layer_max > m_exportBoardCopperLayersCount-2 ) + { + wxMessageBox( + _("The exported board has not enough copper layers to handle selected inner layers") ); + return; + } + EndModal( wxID_OK ); +} diff --git a/gerbview/select_layers_to_pcb.h b/gerbview/select_layers_to_pcb.h new file mode 100644 index 0000000..e9a6eda --- /dev/null +++ b/gerbview/select_layers_to_pcb.h @@ -0,0 +1,72 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011-2014 Jean-Pierre Charras jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see change_log.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file select_layers_to_pcb.h + */ + +#ifndef _SELECT_LAYERS_TO_PCB_H_ +#define _SELECT_LAYERS_TO_PCB_H_ + +#include <dialogs/dialog_layers_select_to_pcb_base.h> + +/* + * This dialog shows the gerber files loaded, and allows user to choose + * equivalence between gerber layers and pcb layers + */ +class LAYERS_MAP_DIALOG : public LAYERS_MAP_DIALOG_BASE +{ +private: + GERBVIEW_FRAME* m_Parent; + int m_gerberActiveLayersCount; // Number of initialized gerber layers + static int m_exportBoardCopperLayersCount; + wxFlexGridSizer* m_flexRightColumnBoxSizer; // An extra wxFlexGridSizer used + // when we have more than 16 gerber files loaded + LAYER_NUM m_layersLookUpTable[GERBER_DRAWLAYERS_COUNT]; // Indexes Gerber layers to PCB file layers + // the last value in table is the number of copper layers + int m_buttonTable[int(GERBER_DRAWLAYERS_COUNT)+1]; // Indexes buttons to Gerber layers + wxStaticText* m_layersList[int(GERBER_DRAWLAYERS_COUNT)+1]; // Indexes text strings to buttons + +public: LAYERS_MAP_DIALOG( GERBVIEW_FRAME* parent ); + ~LAYERS_MAP_DIALOG() {}; + + LAYER_NUM * GetLayersLookUpTable() { return m_layersLookUpTable; } + static int GetCopperLayersCount() { return m_exportBoardCopperLayersCount; } + +private: + void initDialog(); + void normalizeBrdLayersCount(); + void OnBrdLayersCountSelection( wxCommandEvent& event ); + void OnSelectLayer( wxCommandEvent& event ); + void OnOkClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); + + void OnStoreSetup( wxCommandEvent& event ); + void OnGetSetup( wxCommandEvent& event ); + void OnResetClick( wxCommandEvent& event ); + + DECLARE_EVENT_TABLE() +}; + +#endif // _SELECT_LAYERS_TO_PCB_H_ diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp new file mode 100644 index 0000000..9858655 --- /dev/null +++ b/gerbview/toolbars_gerber.cpp @@ -0,0 +1,313 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file toolbars_gerber.cpp + * @brief Build tool bars + */ + +#include <fctsys.h> + +#include <common.h> +#include <macros.h> +#include <gerbview.h> +#include <gerbview_frame.h> +#include <bitmaps.h> +#include <gerbview_id.h> +#include <hotkeys.h> +#include <class_GERBER.h> +#include <class_gbr_layer_box_selector.h> +#include <class_DCodeSelectionbox.h> +#include <dialog_helpers.h> + +void GERBVIEW_FRAME::ReCreateHToolbar( void ) +{ + int ii; + wxString msg; + + if( m_mainToolBar != NULL ) + return; + + m_mainToolBar = new wxAuiToolBar( this, ID_H_TOOLBAR, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_HORZ_LAYOUT ); + + // Set up toolbar + m_mainToolBar->AddTool( ID_GERBVIEW_ERASE_ALL, wxEmptyString, + KiBitmap( gerbview_clear_layers_xpm ), + _( "Erase all layers" ) ); + + m_mainToolBar->AddTool( wxID_FILE, wxEmptyString, KiBitmap( gerber_file_xpm ), + _( "Load a new Gerber file on the current layer. Previous data will be deleted" ) ); + + m_mainToolBar->AddTool( ID_GERBVIEW_LOAD_DRILL_FILE, wxEmptyString, + KiBitmap( gerbview_drill_file_xpm ), + _( "Load an excellon drill file on the current layer. Previous data will be deleted" ) ); + + m_mainToolBar->AddSeparator(); + m_mainToolBar->AddTool( ID_GERBVIEW_SET_PAGE_BORDER, wxEmptyString, KiBitmap( sheetset_xpm ), + _( "Show/hide frame reference and select paper size for printing" ) ); + + m_mainToolBar->AddSeparator(); + m_mainToolBar->AddTool( wxID_PRINT, wxEmptyString, KiBitmap( print_button_xpm ), + _( "Print layers" ) ); + + m_mainToolBar->AddSeparator(); + msg = AddHotkeyName( _( "Zoom in" ), GerbviewHokeysDescr, HK_ZOOM_IN, IS_COMMENT ); + m_mainToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); + + msg = AddHotkeyName( _( "Zoom out" ), GerbviewHokeysDescr, HK_ZOOM_OUT, IS_COMMENT ); + m_mainToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); + + msg = AddHotkeyName( _( "Redraw view" ), GerbviewHokeysDescr, HK_ZOOM_REDRAW, IS_COMMENT ); + m_mainToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); + + msg = AddHotkeyName( _( "Zoom auto" ), GerbviewHokeysDescr, HK_ZOOM_AUTO, IS_COMMENT ); + m_mainToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); + + m_mainToolBar->AddSeparator(); + + m_SelLayerBox = new GBR_LAYER_BOX_SELECTOR( m_mainToolBar, + ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + wxDefaultPosition, wxSize( 150, -1 ), 0,NULL); + m_SelLayerBox->Resync(); + + m_mainToolBar->AddControl( m_SelLayerBox ); + + m_mainToolBar->AddSeparator(); + + m_DCodesList.Alloc(TOOLS_MAX_COUNT+1); + m_DCodesList.Add( _( "No tool" ) ); + + for( ii = FIRST_DCODE; ii < TOOLS_MAX_COUNT; ii++ ) + { + msg = _( "Tool " ); + msg << ii; + m_DCodesList.Add( msg ); + } + + m_DCodeSelector = new DCODE_SELECTION_BOX( m_mainToolBar, + ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, + wxDefaultPosition, wxSize( 150, -1 ), + m_DCodesList ); + m_mainToolBar->AddControl( m_DCodeSelector ); + + m_TextInfo = new wxTextCtrl( m_mainToolBar, wxID_ANY, wxEmptyString, wxDefaultPosition, + wxSize(150,-1), wxTE_READONLY ); + m_mainToolBar->AddControl( m_TextInfo ); + + // after adding the buttons to the toolbar, must call Realize() to reflect the changes + m_mainToolBar->Realize(); +} + + +void GERBVIEW_FRAME::ReCreateVToolbar( void ) +{ + if( m_drawToolBar ) + return; + + m_drawToolBar = new wxAuiToolBar( this, ID_V_TOOLBAR, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_VERTICAL ); + + // Set up toolbar + m_drawToolBar->AddTool( ID_NO_TOOL_SELECTED, wxEmptyString, KiBitmap( cursor_xpm ) ); + m_drawToolBar->AddSeparator(); + + m_drawToolBar->Realize(); +} + + +void GERBVIEW_FRAME::ReCreateOptToolbar( void ) +{ + if( m_optionsToolBar ) + return; + + // creation of tool bar options + m_optionsToolBar = new wxAuiToolBar( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_VERTICAL ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GRID, wxEmptyString, KiBitmap( grid_xpm ), + _( "Turn grid off" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_POLAR_COORD, wxEmptyString, + KiBitmap( polar_coord_xpm ), + _( "Turn polar coordinate on" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_UNIT_INCH, wxEmptyString, + KiBitmap( unit_inch_xpm ), + _( "Set units to inches" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_UNIT_MM, wxEmptyString, + KiBitmap( unit_mm_xpm ), + _( "Set units to millimeters" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SELECT_CURSOR, wxEmptyString, + KiBitmap( cursor_shape_xpm ), + _( "Change cursor shape" ), wxITEM_CHECK ); + + m_optionsToolBar->AddSeparator(); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, wxEmptyString, + KiBitmap( pad_sketch_xpm ), + _( "Show spots in sketch mode" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_LINES_SKETCH, wxEmptyString, + KiBitmap( showtrack_xpm ), + _( "Show lines in sketch mode" ), wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, wxEmptyString, + KiBitmap( opt_show_polygon_xpm ), + _( "Show polygons in sketch mode" ), + wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS, wxEmptyString, + KiBitmap( gerbview_show_negative_objects_xpm ), + _( "Show negatives objects in ghost color" ), + wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_DCODES, wxEmptyString, + KiBitmap( show_dcodenumber_xpm ), + _( "Show dcode number" ), wxITEM_CHECK ); + + // tools to select draw mode in GerbView + m_optionsToolBar->AddSeparator(); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_0, wxEmptyString, + KiBitmap( gbr_select_mode0_xpm ), + _( "Show layers in raw mode \ +(could have problems with negative items when more than one gerber file is shown)" ), + wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_1, wxEmptyString, + KiBitmap( gbr_select_mode1_xpm ), + _( "Show layers in stacked mode \ +(show negative items without artifacts, sometimes slow)" ), + wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_2, wxEmptyString, + KiBitmap( gbr_select_mode2_xpm ), + _( "Show layers in transparency mode \ +(show negative items without artifacts, sometimes slow)" ), + wxITEM_CHECK ); + + // Tools to show/hide toolbars: + m_optionsToolBar->AddSeparator(); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + wxEmptyString, + KiBitmap( layers_manager_xpm ), + _( "Show/hide the layers manager toolbar" ), + wxITEM_CHECK ); + + + m_optionsToolBar->Realize(); +} + + +void GERBVIEW_FRAME::OnUpdateDrawMode( wxUpdateUIEvent& aEvent ) +{ + switch( aEvent.GetId() ) + { + case ID_TB_OPTIONS_SHOW_GBR_MODE_0: + aEvent.Check( GetDisplayMode() == 0 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_1: + aEvent.Check( GetDisplayMode() == 1 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_2: + aEvent.Check( GetDisplayMode() == 2 ); + break; + + default: + break; + } +} + + +void GERBVIEW_FRAME::OnUpdateCoordType( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( m_DisplayOptions.m_DisplayPolarCood ); +} + +void GERBVIEW_FRAME::OnUpdateFlashedItemsDrawMode( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( !m_DisplayOptions.m_DisplayFlashedItemsFill ); +} + + +void GERBVIEW_FRAME::OnUpdateLinesDrawMode( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( !m_DisplayOptions.m_DisplayLinesFill ); +} + + +void GERBVIEW_FRAME::OnUpdatePolygonsDrawMode( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( !m_DisplayOptions.m_DisplayPolygonsFill ); +} + + +void GERBVIEW_FRAME::OnUpdateShowDCodes( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( IsElementVisible( DCODES_VISIBLE ) ); +} + + +void GERBVIEW_FRAME::OnUpdateShowNegativeItems( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( IsElementVisible( NEGATIVE_OBJECTS_VISIBLE ) ); +} + + +void GERBVIEW_FRAME::OnUpdateShowLayerManager( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( m_show_layer_manager_tools ); + + if( m_optionsToolBar ) + { + if( m_show_layer_manager_tools ) + m_optionsToolBar->SetToolShortHelp( aEvent.GetId(), _("Hide layers manager" ) ); + else + m_optionsToolBar->SetToolShortHelp( aEvent.GetId(), _("Show layers manager" ) ); + } +} + + +void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ) +{ + int layer = getActiveLayer(); + GERBER_IMAGE* gerber = g_GERBER_List.GetGbrImage( layer ); + int selected = ( gerber ) ? gerber->m_Selected_Tool : 0; + + if( m_DCodeSelector && m_DCodeSelector->GetSelectedDCodeId() != selected ) + m_DCodeSelector->SetDCodeSelection( selected ); + + aEvent.Enable( gerber != NULL ); +} + + +void GERBVIEW_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ) +{ + if( m_SelLayerBox && (m_SelLayerBox->GetSelection() != getActiveLayer()) ) + { + m_SelLayerBox->SetSelection( getActiveLayer() ); + } +} |