summaryrefslogtreecommitdiff
path: root/gerbview
diff options
context:
space:
mode:
Diffstat (limited to 'gerbview')
-rw-r--r--gerbview/CMakeLists.txt190
-rw-r--r--gerbview/Info.plist55
-rw-r--r--gerbview/block.cpp221
-rw-r--r--gerbview/class_DCodeSelectionbox.cpp84
-rw-r--r--gerbview/class_DCodeSelectionbox.h58
-rw-r--r--gerbview/class_GERBER.cpp557
-rw-r--r--gerbview/class_GERBER.h378
-rw-r--r--gerbview/class_X2_gerber_attributes.cpp270
-rw-r--r--gerbview/class_X2_gerber_attributes.h178
-rw-r--r--gerbview/class_am_param.cpp251
-rw-r--r--gerbview/class_am_param.h268
-rw-r--r--gerbview/class_aperture_macro.cpp811
-rw-r--r--gerbview/class_aperture_macro.h262
-rw-r--r--gerbview/class_excellon.h308
-rw-r--r--gerbview/class_gbr_layer_box_selector.cpp81
-rw-r--r--gerbview/class_gbr_layer_box_selector.h59
-rw-r--r--gerbview/class_gbr_layout.cpp57
-rw-r--r--gerbview/class_gbr_layout.h148
-rw-r--r--gerbview/class_gbr_screen.cpp143
-rw-r--r--gerbview/class_gbr_screen.h69
-rw-r--r--gerbview/class_gerber_draw_item.cpp631
-rw-r--r--gerbview/class_gerber_draw_item.h309
-rw-r--r--gerbview/class_gerbview_layer_widget.cpp338
-rw-r--r--gerbview/class_gerbview_layer_widget.h134
-rw-r--r--gerbview/controle.cpp62
-rw-r--r--gerbview/dcode.cpp531
-rw-r--r--gerbview/dcode.h218
-rw-r--r--gerbview/dialogs/dialog_layers_select_to_pcb_base.cpp119
-rw-r--r--gerbview/dialogs/dialog_layers_select_to_pcb_base.fbp809
-rw-r--r--gerbview/dialogs/dialog_layers_select_to_pcb_base.h88
-rw-r--r--gerbview/dialogs/dialog_print_using_printer.cpp404
-rw-r--r--gerbview/dialogs/dialog_print_using_printer_base.cpp138
-rw-r--r--gerbview/dialogs/dialog_print_using_printer_base.fbp1167
-rw-r--r--gerbview/dialogs/dialog_print_using_printer_base.h78
-rw-r--r--gerbview/dialogs/dialog_select_one_pcb_layer.cpp277
-rw-r--r--gerbview/dialogs/dialog_show_page_borders.cpp84
-rw-r--r--gerbview/dialogs/dialog_show_page_borders.h47
-rw-r--r--gerbview/dialogs/dialog_show_page_borders_base.cpp64
-rw-r--r--gerbview/dialogs/dialog_show_page_borders_base.fbp316
-rw-r--r--gerbview/dialogs/dialog_show_page_borders_base.h55
-rw-r--r--gerbview/dialogs/gerbview_dialog_display_options_frame.cpp182
-rw-r--r--gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp141
-rw-r--r--gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp1334
-rw-r--r--gerbview/dialogs/gerbview_dialog_display_options_frame_base.h71
-rw-r--r--gerbview/draw_gerber_screen.cpp457
-rw-r--r--gerbview/events_called_functions.cpp390
-rw-r--r--gerbview/excellon_read_drill_file.cpp702
-rw-r--r--gerbview/export_to_pcbnew.cpp495
-rw-r--r--gerbview/files.cpp303
-rw-r--r--gerbview/gerber_test_files/aperture-circle-flash-with_hole.gbr27
-rw-r--r--gerbview/gerber_test_files/aperture-obround-flash-with_hole.gbr27
-rw-r--r--gerbview/gerber_test_files/aperture_macro-no_param-test.gbr82
-rw-r--r--gerbview/gerber_test_files/aperture_macro-with_param-test.gbr99
-rw-r--r--gerbview/gerber_test_files/apertures_rotated.gbr1109
-rw-r--r--gerbview/gerber_test_files/apertures_rotated_and_arcs_in_tracks.gbr1417
-rw-r--r--gerbview/gerber_test_files/octogonal.gbr27
-rw-r--r--gerbview/gerber_test_files/test-aperture-polygon-flash.gbr27
-rw-r--r--gerbview/gerber_test_files/test-aperture-rectangle-flash-with_hole.gbr27
-rw-r--r--gerbview/gerber_test_files/test-image-justify-with-offset.gbr19
-rw-r--r--gerbview/gerber_test_files/test-image-offset.gbr18
-rw-r--r--gerbview/gerber_test_files/test-image-polarity.gbr17
-rw-r--r--gerbview/gerber_test_files/test-image-rotation.gbr21
-rw-r--r--gerbview/gerber_test_files/test-layer-axis-select.gbr15
-rw-r--r--gerbview/gerber_test_files/test-layer-mixed_units_mode.gbr68
-rw-r--r--gerbview/gerber_test_files/test-layer-rotation.gbr23
-rw-r--r--gerbview/gerber_test_files/test-layer-scale-factor.gbr17
-rw-r--r--gerbview/gerber_test_files/test-layer-step-and_repeat-cross.gbr17
-rw-r--r--gerbview/gerber_test_files/test-layer-step-and_repeat-polygon.gbr18
-rw-r--r--gerbview/gerber_test_files/test-polygon_with_arc-fill.gbr18
-rw-r--r--gerbview/gerber_test_files/test2_line_with_rect_aperture.gbr67
-rw-r--r--gerbview/gerber_test_files/test_line_with_rect_aperture.gbr16
-rw-r--r--gerbview/gerber_test_files/test_polygons_with_arcs.gbr4163
-rw-r--r--gerbview/gerber_test_files/test_polygons_with_arcs_simple.gbr51
-rw-r--r--gerbview/gerbview.cpp152
-rw-r--r--gerbview/gerbview.h109
-rw-r--r--gerbview/gerbview.icnsbin0 -> 253784 bytes
-rw-r--r--gerbview/gerbview.rc3
-rw-r--r--gerbview/gerbview_config.cpp148
-rw-r--r--gerbview/gerbview_doc.icnsbin0 -> 153778 bytes
-rw-r--r--gerbview/gerbview_frame.cpp835
-rw-r--r--gerbview/gerbview_frame.h694
-rw-r--r--gerbview/gerbview_id.h81
-rw-r--r--gerbview/hotkeys.cpp216
-rw-r--r--gerbview/hotkeys.h51
-rw-r--r--gerbview/init_gbr_drawlayers.cpp98
-rw-r--r--gerbview/locate.cpp88
-rw-r--r--gerbview/menubar.cpp257
-rw-r--r--gerbview/onleftclick.cpp60
-rw-r--r--gerbview/onrightclick.cpp95
-rw-r--r--gerbview/options.cpp97
-rw-r--r--gerbview/pcbplot.cpp36
-rw-r--r--gerbview/pcbplot.h40
-rw-r--r--gerbview/printout_control.cpp269
-rw-r--r--gerbview/readgerb.cpp199
-rw-r--r--gerbview/rs274_read_XY_and_IJ_coordinates.cpp305
-rw-r--r--gerbview/rs274d.cpp771
-rw-r--r--gerbview/rs274x.cpp1064
-rw-r--r--gerbview/select_layers_to_pcb.cpp428
-rw-r--r--gerbview/select_layers_to_pcb.h72
-rw-r--r--gerbview/toolbars_gerber.cpp313
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">&quot;2 Layers&quot; &quot;4 Layers&quot; &quot;6 Layers&quot; &quot;8 Layers&quot; &quot;10 Layers&quot; &quot;12 Layers&quot; &quot;14 Layers&quot; &quot;16 Layers&quot;</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">&quot;fit in page&quot; &quot;Scale 0.5&quot; &quot;Scale 0.7&quot; &quot;Approx. Scale 1&quot; &quot;Accurate Scale 1&quot; &quot;Scale 1.4&quot; &quot;Scale 2&quot; &quot;Scale 3&quot; &quot;Scale 4&quot;</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">&quot;Color&quot; &quot;Black and white&quot;</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">&quot;Full size. Do not show page limits&quot; &quot;Full size&quot; &quot;Size A4&quot; &quot;Size A3&quot; &quot;Size A2&quot; &quot;Size A&quot; &quot;Size B&quot; &quot;Size C&quot;</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">&quot;Cartesian coordinates&quot; &quot;Polar coordinates&quot;</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">&quot;Inches&quot; &quot;Millimeters&quot;</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">&quot;Small cross&quot; &quot;Full screen cursor&quot;</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">&quot;Sketch&quot; &quot;Filled&quot;</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">&quot;Sketch&quot; &quot;Filled&quot;</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">&quot;Sketch&quot; &quot;Filled&quot;</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">&quot;Full size without limits&quot; &quot;Full size&quot; &quot;Size A4&quot; &quot;Size A3&quot; &quot;Size A2&quot; &quot;Size A&quot; &quot;Size B&quot; &quot;Size C&quot;</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 &lt;%c&gt;" ), *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 &lt;%s&gt;" ), 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: &lt;%s&gt;" ), 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
new file mode 100644
index 0000000..4ba9792
--- /dev/null
+++ b/gerbview/gerbview.icns
Binary files differ
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
new file mode 100644
index 0000000..4b6de4a
--- /dev/null
+++ b/gerbview/gerbview_doc.icns
Binary files differ
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 &ltname&gt command) in the status bar
+ * Name of the Image (found in the gerber file: IN &ltname&gt 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() );
+ }
+}