Commit 7edce2fa authored by Garth Corral's avatar Garth Corral

Merge trunk @ 5266

parents a0e0958c 1aec1f59
...@@ -273,20 +273,15 @@ if( USE_OSX_MAGNIFY_EVENT ) ...@@ -273,20 +273,15 @@ if( USE_OSX_MAGNIFY_EVENT )
endif() endif()
# Allow user to override the default settings for adding images to menu items. By default # By default images in menu items are enabled on all platforms except OSX.
# images in menu items are enabled on all platforms except OSX. This can be over ridden by if( NOT APPLE )
# defining -DUSE_IMAGES_IN_MENUS=ON/OFF to force the preferred behavior. set( USE_IMAGES_IN_MENUS ON CACHE BOOL "Enable images in menus" )
if( NOT DEFINED USE_IMAGES_IN_MENUS )
if( NOT APPLE )
set( USE_IMAGES_IN_MENUS ON )
endif()
else() else()
if( USE_IMAGES_IN_MENUS ) set( USE_IMAGES_IN_MENUS OFF CACHE BOOL "Enable images in menus" )
set( USE_IMAGES_IN_MENUS ON )
endif()
endif() endif()
# KIFACE_SUFFIX is the file extension used for top level program modules which # KIFACE_SUFFIX is the file extension used for top level program modules which
# implement the KIFACE interface. A valid suffix starts with a period '.'. # implement the KIFACE interface. A valid suffix starts with a period '.'.
......
...@@ -130,10 +130,10 @@ In order to have a working Kicad installtion, you need ...@@ -130,10 +130,10 @@ In order to have a working Kicad installtion, you need
- documentation and translations (they are not included in sources) - documentation and translations (they are not included in sources)
product branch: product branch:
bzr branch lp:kicad kicad_src bzr branch https://code.launchpad.net/~kicad-product-committers/kicad kicad_src
Stable branch: Stable branch:
bzr branch lp:kicad/stable kicad_src bzr branch https://code.launchpad.net/~kicad-product-committers/kicad/stable kicad_src
Components and Footprints libraries Components and Footprints libraries
all (schematic libs, 3D shapes ...) but new footprints libraries (use Download zip tool) all (schematic libs, 3D shapes ...) but new footprints libraries (use Download zip tool)
......
...@@ -14,7 +14,7 @@ boost libraries will be downloaded the first time you build Kicad. ...@@ -14,7 +14,7 @@ boost libraries will be downloaded the first time you build Kicad.
CMake CMake
===== =====
KiCad uses CMake to generate the build files specific for the target platform KiCad uses CMake (version 2.12 or later) to generate the build files specific for the target platform
specified by the developer. This document attempts to define some of the more specified by the developer. This document attempts to define some of the more
common CMake and KiCad build configuration settings. You can use CMake either common CMake and KiCad build configuration settings. You can use CMake either
by the command CMake on or the graphical version ccmake. This document only by the command CMake on or the graphical version ccmake. This document only
...@@ -78,24 +78,6 @@ the wxWidgets library. If you wish to use a custom built wxWidgets library, ...@@ -78,24 +78,6 @@ the wxWidgets library. If you wish to use a custom built wxWidgets library,
set wxWidgets_ROOT_DIR to the correct path. set wxWidgets_ROOT_DIR to the correct path.
wxWidgets_USE_DEBUG (ON/OFF)
----------------------------
Default: OFF
When creating a debug build of KiCad, it is often useful to link against the
debug build of the wxWidgets. To use the debug build of wxWidgets, set
wxWidgets_USE_DEBUG to ON.
wxWidgets_USE_UNICODE (ON/OFF)
------------------------------
Default: ON (wxWidgets 2.9 or later), OFF (older versions)
If your platform supports Unicode and you wish to build KiCad with Unicode
support, set wxWidgets_USE_UNICODE to ON. Please note as of the 2.9 branch
this option is not required.
KiCad Specific Options KiCad Specific Options
====================== ======================
...@@ -114,17 +96,6 @@ WARNING: The KiCad developers strongly advise you to build the bundled copy of ...@@ -114,17 +96,6 @@ WARNING: The KiCad developers strongly advise you to build the bundled copy of
the Boost library, as it is known to work with KiCad. Other versions may the Boost library, as it is known to work with KiCad. Other versions may
contain bugs that may result in KiCad errors. contain bugs that may result in KiCad errors.
USE_WX_GRAPHICS_CONTEXT (ON/OFF)
--------------------------------
Default: OFF
This option is *Experimental*. It enables advanced drawing library code using
wxGraphicsContext and should only be used for testing purposes. Under Windows,
a very recent version of mingw is needed. It also requires wxWidgets to be
built with the --enable-graphics_ctx configuration switch.
USE_IMAGES_IN_MENUS (ON/OFF) USE_IMAGES_IN_MENUS (ON/OFF)
---------------------------- ----------------------------
Default: OFF for OSX, ON for other platforms. Default: OFF for OSX, ON for other platforms.
...@@ -147,20 +118,11 @@ to avoid download and building the dependencies multiple times. ...@@ -147,20 +118,11 @@ to avoid download and building the dependencies multiple times.
KICAD_USER_CONFIG_DIR (PATH) KICAD_USER_CONFIG_DIR (PATH)
---------------------------- ----------------------------
Default: Home directory (Unix-based systems), Application data directory (Windows) Default: ~/.config (Unix-based systems), Application data directory (Windows)
This option specifies where to store user-specific configuration information. This option specifies where to store user-specific configuration information.
KICAD_KEEPCASE (ON/OFF)
-----------------------
Default: ON
If this is OFF, component names are automatically converted to uppercase meaning
they are case insensitive. If it is ON, component names are not changed and
are therefore case sensitive.
USE_WX_OVERLAY (ON/OFF) USE_WX_OVERLAY (ON/OFF)
----------------------- -----------------------
Default: ON for OSX, OFF for other platforms. Default: ON for OSX, OFF for other platforms.
...@@ -192,7 +154,7 @@ KICAD_SCRIPTING_WXPYTHON (ON/OFF) ...@@ -192,7 +154,7 @@ KICAD_SCRIPTING_WXPYTHON (ON/OFF)
Default: OFF Default: OFF
This option enables or disables building wxPython support into the KiCad This option enables or disables building wxPython support into the KiCad
scripting support. Currently only Pcbnew is supported. This option requires scripting support. Currently only Pcbnew has scripting support. This option requires
SWIG, Python, and wxPython to be installed on the system. SWIG, Python, and wxPython to be installed on the system.
......
...@@ -103,16 +103,16 @@ install the wxWidgets library into MinGW then enter the following commands: ...@@ -103,16 +103,16 @@ install the wxWidgets library into MinGW then enter the following commands:
#mkdir Release #mkdir Release
#cd Release #cd Release
#../configure --with-opengl #../configure --enable-monolithic=no --enable-shared=yes --with-opengl
#make #make
If you want to install wxWidgets in MinGW then enter the following commands: If you want to install wxWidgets in MinGW then enter the following commands:
#mkdir Release #mkdir Release
#cd Release #cd Release
#../configure --prefix=/mingw --enable-monolithic=no --disable-shared --with-opengl #../configure --prefix=/mingw --enable-monolithic=no --enable-shared=yes --with-opengl
#make && make install #make && make install
wxWidgets will be statically linked to Kicad, which avoid issus with wxWidgets dlls wxWidgets cannot be statically linked to Kicad.
Download the KiCad Source Code Download the KiCad Source Code
------------------------------ ------------------------------
...@@ -126,16 +126,19 @@ Launchpad repository has two branches for KiCad sources: ...@@ -126,16 +126,19 @@ Launchpad repository has two branches for KiCad sources:
near a stable state) near a stable state)
To download the testing branch: To download the testing branch:
#bzr branch lp:kicad kicad_testing #bzr branch https://code.launchpad.net/~kicad-product-committers/kicad kicad_testing
To download the stable branch: To download the stable branch:
#bzr branch lp:kicad/stable kicad_stable #bzr branch https://code.launchpad.net/~kicad-product-committers/kicad/stable kicad_stable
To download the component and footprint libraries To download the component and footprint libraries:
#bzr branch lp:~kicad-lib-committers/kicad/library kicad_libraries (This branch is a bzr/launchpad import of the Git repository
at https://github.com/KiCad/kicad-library.git.
It has schematic parts and 3D models in it.)
#bzr branch https://code.launchpad.net/~kicad-product-committers/kicad/library kicad_libraries
To download the documentation and translation files: To download the documentation and translation files:
#bzr branch lp:~kicad-developers/kicad/doc kicad_doc #bzr branch https://code.launchpad.net/~kicad-developers/kicad/doc kicad_doc
Create Makefiles with CMake Create Makefiles with CMake
--------------------------- ---------------------------
...@@ -219,7 +222,7 @@ Building the Developer Documentation ...@@ -219,7 +222,7 @@ Building the Developer Documentation
------------------------------------ ------------------------------------
To build the HTML developer documentation, run the following commands: To build the HTML developer documentation, run the following commands:
#cd <kicadSource>/build/debug #cd <kicadSource>/build/release
#make doxygen-docs #make doxygen-docs
The documentation will be created in the <kicadSouce>/Documentation/html The documentation will be created in the <kicadSouce>/Documentation/html
......
...@@ -50,13 +50,15 @@ ...@@ -50,13 +50,15 @@
#define KEYWORD_LAST_INPUT_FILE wxT( "Last_input" ) #define KEYWORD_LAST_INPUT_FILE wxT( "Last_input" )
#define KEYWORD_LAST_OUTPUT_FILE wxT( "Last_output" ) #define KEYWORD_LAST_OUTPUT_FILE wxT( "Last_output" )
#define KEYWORD_LAST_FORMAT wxT( "Last_format" ) #define KEYWORD_LAST_FORMAT wxT( "Last_format" )
#define KEYWORD_LAST_MODLAYER wxT( "Last_modlayer" )
#define KEYWORD_BINARY_THRESHOLD wxT( "Threshold" ) #define KEYWORD_BINARY_THRESHOLD wxT( "Threshold" )
#define KEYWORD_BW_NEGATIVE wxT( "Negative_choice" ) #define KEYWORD_BW_NEGATIVE wxT( "Negative_choice" )
#define DEFAULT_DPI 300 // Default resolution in Bit per inches #define DEFAULT_DPI 300 // Default resolution in Bit per inches
extern int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, extern int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y ); OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y,
BMP2CMP_MOD_LAYER aModLayer );
/** /**
* Class BM2CMP_FRAME_BASE * Class BM2CMP_FRAME_BASE
...@@ -138,6 +140,7 @@ private: ...@@ -138,6 +140,7 @@ private:
void NegateGreyscaleImage( ); void NegateGreyscaleImage( );
void ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat ); void ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat );
void updateImageInfo(); void updateImageInfo();
void OnFormatChange( wxCommandEvent& event );
}; };
...@@ -169,6 +172,19 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) : ...@@ -169,6 +172,19 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_radioBoxFormat->SetSelection( tmp ); m_radioBoxFormat->SetSelection( tmp );
} }
if( tmp == PCBNEW_KICAD_MOD )
m_radio_PCBLayer->Enable( true );
else
m_radio_PCBLayer->Enable( false );
if( m_config->Read( KEYWORD_LAST_MODLAYER, &tmp ) )
{
if( (unsigned) tmp > MOD_LYR_FINAL ) // Out of range
m_radio_PCBLayer->SetSelection( MOD_LYR_FSILKS );
else
m_radio_PCBLayer->SetSelection( tmp );
}
// Give an icon // Give an icon
wxIcon icon; wxIcon icon;
icon.CopyFromBitmap( KiBitmap( icon_bitmap2component_xpm ) ); icon.CopyFromBitmap( KiBitmap( icon_bitmap2component_xpm ) );
...@@ -204,6 +220,7 @@ BM2CMP_FRAME::~BM2CMP_FRAME() ...@@ -204,6 +220,7 @@ BM2CMP_FRAME::~BM2CMP_FRAME()
m_config->Write( KEYWORD_BINARY_THRESHOLD, m_sliderThreshold->GetValue() ); m_config->Write( KEYWORD_BINARY_THRESHOLD, m_sliderThreshold->GetValue() );
m_config->Write( KEYWORD_BW_NEGATIVE, m_rbOptions->GetSelection() ); m_config->Write( KEYWORD_BW_NEGATIVE, m_rbOptions->GetSelection() );
m_config->Write( KEYWORD_LAST_FORMAT, m_radioBoxFormat->GetSelection() ); m_config->Write( KEYWORD_LAST_FORMAT, m_radioBoxFormat->GetSelection() );
m_config->Write( KEYWORD_LAST_MODLAYER, m_radio_PCBLayer->GetSelection() );
delete m_config; delete m_config;
...@@ -628,7 +645,14 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat ) ...@@ -628,7 +645,14 @@ void BM2CMP_FRAME::ExportFile( FILE* aOutfile, OUTPUT_FMT_ID aFormat )
} }
} }
bitmap2component( potrace_bitmap, aOutfile, aFormat, m_imageDPI.x, m_imageDPI.y ); // choices of m_radio_PCBLayer are expected to be in same order as
// BMP2CMP_MOD_LAYER. See bitmap2component.h
BMP2CMP_MOD_LAYER modLayer = MOD_LYR_FSILKS;
if( aFormat == PCBNEW_KICAD_MOD )
modLayer = (BMP2CMP_MOD_LAYER) m_radio_PCBLayer->GetSelection();
bitmap2component( potrace_bitmap, aOutfile, aFormat, m_imageDPI.x, m_imageDPI.y, modLayer );
} }
...@@ -711,3 +735,12 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) ...@@ -711,3 +735,12 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
return start_common( aCtlBits ); return start_common( aCtlBits );
} }
void BM2CMP_FRAME::OnFormatChange( wxCommandEvent& event )
{
if( m_radioBoxFormat->GetSelection() == PCBNEW_KICAD_MOD )
m_radio_PCBLayer->Enable( true );
else
m_radio_PCBLayer->Enable( false );
event.Skip();
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Nov 6 2013) // C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO "NOT" EDIT THIS FILE! // PLEASE DO "NOT" EDIT THIS FILE!
...@@ -16,22 +16,22 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS ...@@ -16,22 +16,22 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS
wxBoxSizer* bMainSizer; wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxHORIZONTAL ); bMainSizer = new wxBoxSizer( wxHORIZONTAL );
m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); m_Notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_InitialPicturePanel = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); m_InitialPicturePanel = new wxScrolledWindow( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
m_InitialPicturePanel->SetScrollRate( 5, 5 ); m_InitialPicturePanel->SetScrollRate( 5, 5 );
m_InitialPicturePanel->SetMinSize( wxSize( 400,300 ) ); m_InitialPicturePanel->SetMinSize( wxSize( 400,300 ) );
m_notebook1->AddPage( m_InitialPicturePanel, _("Original Picture"), true ); m_Notebook->AddPage( m_InitialPicturePanel, _("Original Picture"), true );
m_GreyscalePicturePanel = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); m_GreyscalePicturePanel = new wxScrolledWindow( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
m_GreyscalePicturePanel->SetScrollRate( 5, 5 ); m_GreyscalePicturePanel->SetScrollRate( 5, 5 );
m_GreyscalePicturePanel->SetMinSize( wxSize( 400,300 ) ); m_GreyscalePicturePanel->SetMinSize( wxSize( 400,300 ) );
m_notebook1->AddPage( m_GreyscalePicturePanel, _("Greyscale Picture"), false ); m_Notebook->AddPage( m_GreyscalePicturePanel, _("Greyscale Picture"), false );
m_BNPicturePanel = new wxScrolledWindow( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); m_BNPicturePanel = new wxScrolledWindow( m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL );
m_BNPicturePanel->SetScrollRate( 5, 5 ); m_BNPicturePanel->SetScrollRate( 5, 5 );
m_notebook1->AddPage( m_BNPicturePanel, _("Black&&White Picture"), false ); m_Notebook->AddPage( m_BNPicturePanel, _("Black&&White Picture"), false );
bMainSizer->Add( m_notebook1, 1, wxEXPAND, 5 ); bMainSizer->Add( m_Notebook, 1, wxEXPAND, 5 );
m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_panelRight = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* brightSizer; wxBoxSizer* brightSizer;
...@@ -147,6 +147,14 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS ...@@ -147,6 +147,14 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS
brightSizer->Add( m_sliderThreshold, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); brightSizer->Add( m_sliderThreshold, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
wxString m_radio_PCBLayerChoices[] = { _("Front silk screen"), _("Front solder mask"), _("User layer Eco1"), _("User Layer Eco2") };
int m_radio_PCBLayerNChoices = sizeof( m_radio_PCBLayerChoices ) / sizeof( wxString );
m_radio_PCBLayer = new wxRadioBox( m_panelRight, wxID_ANY, _("Board Layer for Outline:"), wxDefaultPosition, wxDefaultSize, m_radio_PCBLayerNChoices, m_radio_PCBLayerChoices, 1, wxRA_SPECIFY_COLS );
m_radio_PCBLayer->SetSelection( 0 );
m_radio_PCBLayer->SetToolTip( _("Choose the board layer to place the outline.\nThe 2 invisible fields reference and value and always placed on the silk screen layer.") );
brightSizer->Add( m_radio_PCBLayer, 0, wxALL|wxEXPAND, 5 );
m_panelRight->SetSizer( brightSizer ); m_panelRight->SetSizer( brightSizer );
m_panelRight->Layout(); m_panelRight->Layout();
...@@ -168,6 +176,7 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS ...@@ -168,6 +176,7 @@ BM2CMP_FRAME_BASE::BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id, const wxS
m_DPIValueY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_DPIValueY->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this );
m_buttonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this ); m_buttonLoad->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this );
m_buttonExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this ); m_buttonExport->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this );
m_radioBoxFormat->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnFormatChange ), NULL, this );
m_rbOptions->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnOptionsSelection ), NULL, this ); m_rbOptions->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnOptionsSelection ), NULL, this );
m_sliderThreshold->Connect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this ); m_sliderThreshold->Connect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this );
} }
...@@ -184,6 +193,7 @@ BM2CMP_FRAME_BASE::~BM2CMP_FRAME_BASE() ...@@ -184,6 +193,7 @@ BM2CMP_FRAME_BASE::~BM2CMP_FRAME_BASE()
m_DPIValueY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this ); m_DPIValueY->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnResolutionChange ), NULL, this );
m_buttonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this ); m_buttonLoad->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnLoadFile ), NULL, this );
m_buttonExport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this ); m_buttonExport->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnExport ), NULL, this );
m_radioBoxFormat->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnFormatChange ), NULL, this );
m_rbOptions->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnOptionsSelection ), NULL, this ); m_rbOptions->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( BM2CMP_FRAME_BASE::OnOptionsSelection ), NULL, this );
m_sliderThreshold->Disconnect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this ); m_sliderThreshold->Disconnect( wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler( BM2CMP_FRAME_BASE::OnThresholdChange ), NULL, this );
......
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project> <wxFormBuilder_Project>
<FileVersion major="1" minor="11" /> <FileVersion major="1" minor="13" />
<object class="Project" expanded="1"> <object class="Project" expanded="1">
<property name="class_decoration"></property> <property name="class_decoration"></property>
<property name="code_generation">C++</property> <property name="code_generation">C++</property>
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="name">BM2CMP_FRAME_BASE</property> <property name="name">BM2CMP_FRAME_BASE</property>
<property name="pos"></property> <property name="pos"></property>
<property name="size">527,470</property> <property name="size">733,634</property>
<property name="style">wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER</property> <property name="style">wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER</property>
<property name="subclass">KIWAY_PLAYER; kiway_player.h</property> <property name="subclass">KIWAY_PLAYER; kiway_player.h</property>
<property name="title">Bitmap to Component Converter</property> <property name="title">Bitmap to Component Converter</property>
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
<property name="moveable">1</property> <property name="moveable">1</property>
<property name="name">m_notebook1</property> <property name="name">m_Notebook</property>
<property name="pane_border">1</property> <property name="pane_border">1</property>
<property name="pane_position"></property> <property name="pane_position"></property>
<property name="pane_size"></property> <property name="pane_size"></property>
...@@ -522,7 +522,7 @@ ...@@ -522,7 +522,7 @@
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND|wxBOTTOM</property> <property name="flag">wxEXPAND|wxBOTTOM</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxFlexGridSizer" expanded="1"> <object class="wxFlexGridSizer" expanded="0">
<property name="cols">4</property> <property name="cols">4</property>
<property name="flexible_direction">wxBOTH</property> <property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1,2</property> <property name="growablecols">1,2</property>
...@@ -534,11 +534,11 @@ ...@@ -534,11 +534,11 @@
<property name="permission">none</property> <property name="permission">none</property>
<property name="rows">0</property> <property name="rows">0</property>
<property name="vgap">0</property> <property name="vgap">0</property>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxALIGN_RIGHT|wxALL|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -617,11 +617,11 @@ ...@@ -617,11 +617,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -700,11 +700,11 @@ ...@@ -700,11 +700,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -783,11 +783,11 @@ ...@@ -783,11 +783,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -866,11 +866,11 @@ ...@@ -866,11 +866,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_RIGHT</property> <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_RIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -949,11 +949,11 @@ ...@@ -949,11 +949,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT</property> <property name="flag">wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1032,11 +1032,11 @@ ...@@ -1032,11 +1032,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT</property> <property name="flag">wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1115,11 +1115,11 @@ ...@@ -1115,11 +1115,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT</property> <property name="flag">wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1198,11 +1198,11 @@ ...@@ -1198,11 +1198,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1281,11 +1281,11 @@ ...@@ -1281,11 +1281,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1364,11 +1364,11 @@ ...@@ -1364,11 +1364,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1447,21 +1447,21 @@ ...@@ -1447,21 +1447,21 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxEXPAND</property> <property name="flag">wxEXPAND</property>
<property name="proportion">1</property> <property name="proportion">1</property>
<object class="spacer" expanded="1"> <object class="spacer" expanded="0">
<property name="height">0</property> <property name="height">0</property>
<property name="permission">protected</property> <property name="permission">protected</property>
<property name="width">0</property> <property name="width">0</property>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property> <property name="flag">wxALIGN_RIGHT|wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1540,11 +1540,11 @@ ...@@ -1540,11 +1540,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxBOTTOM|wxRIGHT</property> <property name="flag">wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1"> <object class="wxTextCtrl" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1631,11 +1631,11 @@ ...@@ -1631,11 +1631,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxTextCtrl" expanded="1"> <object class="wxTextCtrl" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -1722,11 +1722,11 @@ ...@@ -1722,11 +1722,11 @@
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
<object class="sizeritem" expanded="1"> <object class="sizeritem" expanded="0">
<property name="border">5</property> <property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property> <property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property> <property name="proportion">0</property>
<object class="wxStaticText" expanded="1"> <object class="wxStaticText" expanded="0">
<property name="BottomDockable">1</property> <property name="BottomDockable">1</property>
<property name="LeftDockable">1</property> <property name="LeftDockable">1</property>
<property name="RightDockable">1</property> <property name="RightDockable">1</property>
...@@ -2066,7 +2066,7 @@ ...@@ -2066,7 +2066,7 @@
<event name="OnMouseEvents"></event> <event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event> <event name="OnMouseWheel"></event>
<event name="OnPaint"></event> <event name="OnPaint"></event>
<event name="OnRadioBox"></event> <event name="OnRadioBox">OnFormatChange</event>
<event name="OnRightDClick"></event> <event name="OnRightDClick"></event>
<event name="OnRightDown"></event> <event name="OnRightDown"></event>
<event name="OnRightUp"></event> <event name="OnRightUp"></event>
...@@ -2356,6 +2356,96 @@ ...@@ -2356,6 +2356,96 @@
<event name="OnUpdateUI"></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;Front silk screen&quot; &quot;Front solder mask&quot; &quot;User layer Eco1&quot; &quot;User Layer Eco2&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">Board Layer for Outline:</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_radio_PCBLayer</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 the board layer to place the outline.&#x0A;The 2 invisible fields reference and value and always placed on the silk screen layer.</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> </object>
......
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Nov 6 2013) // C++ code generated with wxFormBuilder (version Jun 5 2014)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO "NOT" EDIT THIS FILE! // PLEASE DO "NOT" EDIT THIS FILE!
...@@ -46,7 +46,7 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER ...@@ -46,7 +46,7 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER
private: private:
protected: protected:
wxNotebook* m_notebook1; wxNotebook* m_Notebook;
wxScrolledWindow* m_InitialPicturePanel; wxScrolledWindow* m_InitialPicturePanel;
wxScrolledWindow* m_GreyscalePicturePanel; wxScrolledWindow* m_GreyscalePicturePanel;
wxScrolledWindow* m_BNPicturePanel; wxScrolledWindow* m_BNPicturePanel;
...@@ -72,6 +72,7 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER ...@@ -72,6 +72,7 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER
wxRadioBox* m_rbOptions; wxRadioBox* m_rbOptions;
wxStaticText* m_ThresholdText; wxStaticText* m_ThresholdText;
wxSlider* m_sliderThreshold; wxSlider* m_sliderThreshold;
wxRadioBox* m_radio_PCBLayer;
wxStatusBar* m_statusBar; wxStatusBar* m_statusBar;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
...@@ -81,13 +82,14 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER ...@@ -81,13 +82,14 @@ class BM2CMP_FRAME_BASE : public KIWAY_PLAYER
virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); } virtual void UpdatePPITextValueY( wxMouseEvent& event ) { event.Skip(); }
virtual void OnLoadFile( wxCommandEvent& event ) { event.Skip(); } virtual void OnLoadFile( wxCommandEvent& event ) { event.Skip(); }
virtual void OnExport( wxCommandEvent& event ) { event.Skip(); } virtual void OnExport( wxCommandEvent& event ) { event.Skip(); }
virtual void OnFormatChange( wxCommandEvent& event ) { event.Skip(); }
virtual void OnOptionsSelection( wxCommandEvent& event ) { event.Skip(); } virtual void OnOptionsSelection( wxCommandEvent& event ) { event.Skip(); }
virtual void OnThresholdChange( wxScrollEvent& event ) { event.Skip(); } virtual void OnThresholdChange( wxScrollEvent& event ) { event.Skip(); }
public: public:
BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bitmap to Component Converter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 527,470 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL ); BM2CMP_FRAME_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bitmap to Component Converter"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 733,634 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~BM2CMP_FRAME_BASE(); ~BM2CMP_FRAME_BASE();
......
...@@ -86,7 +86,7 @@ public: ...@@ -86,7 +86,7 @@ public:
* Creates the output file specified by m_Outfile, * Creates the output file specified by m_Outfile,
* depending on file format given by m_Format * depending on file format given by m_Format
*/ */
void CreateOutputFile(); void CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer = (BMP2CMP_MOD_LAYER) 0 );
private: private:
...@@ -94,7 +94,7 @@ private: ...@@ -94,7 +94,7 @@ private:
* Function OuputFileHeader * Function OuputFileHeader
* write to file the header depending on file format * write to file the header depending on file format
*/ */
void OuputFileHeader(); void OuputFileHeader( const char * aBrdLayerName );
/** /**
* Function OuputFileEnd * Function OuputFileEnd
...@@ -103,12 +103,18 @@ private: ...@@ -103,12 +103,18 @@ private:
void OuputFileEnd(); void OuputFileEnd();
/**
* @return the board layer name depending on the board layer selected
* @param aChoice = the choice (MOD_LYR_FSILKS to MOD_LYR_FINAL)
*/
const char * getBrdLayerName( BMP2CMP_MOD_LAYER aChoice );
/** /**
* Function OuputOnePolygon * Function OuputOnePolygon
* write one polygon to output file. * write one polygon to output file.
* Polygon coordinates are expected scaled by the polugon extraction function * Polygon coordinates are expected scaled by the polugon extraction function
*/ */
void OuputOnePolygon( KPolygon & aPolygon ); void OuputOnePolygon( KPolygon & aPolygon, const char * aBrdLayerName );
}; };
...@@ -133,7 +139,8 @@ BITMAPCONV_INFO::BITMAPCONV_INFO() ...@@ -133,7 +139,8 @@ BITMAPCONV_INFO::BITMAPCONV_INFO()
int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y ) OUTPUT_FMT_ID aFormat, int aDpi_X, int aDpi_Y,
BMP2CMP_MOD_LAYER aModLayer )
{ {
potrace_param_t* param; potrace_param_t* param;
potrace_state_t* st; potrace_state_t* st;
...@@ -189,7 +196,7 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, ...@@ -189,7 +196,7 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
info.m_Format = PCBNEW_KICAD_MOD; info.m_Format = PCBNEW_KICAD_MOD;
info.m_ScaleX = 1e6 * 25.4 / aDpi_X; // the conversion scale from PPI to UI info.m_ScaleX = 1e6 * 25.4 / aDpi_X; // the conversion scale from PPI to UI
info.m_ScaleY = 1e6 * 25.4 / aDpi_Y; // Y axis is top to bottom in modedit info.m_ScaleY = 1e6 * 25.4 / aDpi_Y; // Y axis is top to bottom in modedit
info.CreateOutputFile(); info.CreateOutputFile( aModLayer );
break; break;
default: default:
...@@ -204,8 +211,33 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile, ...@@ -204,8 +211,33 @@ int bitmap2component( potrace_bitmap_t* aPotrace_bitmap, FILE* aOutfile,
return 0; return 0;
} }
const char* BITMAPCONV_INFO::getBrdLayerName( BMP2CMP_MOD_LAYER aChoice )
{
const char * layerName = "F.SilkS";
switch( aChoice )
{
case MOD_LYR_FSOLDERMASK:
layerName = "F.Mask";
break;
case MOD_LYR_ECO1:
layerName = "Eco1.User";
break;
case MOD_LYR_ECO2:
layerName = "Eco2.User";
break;
case MOD_LYR_FSILKS:
default: // case MOD_LYR_FSILKS only unless there is a bug
break;
}
return layerName;
}
void BITMAPCONV_INFO::OuputFileHeader() void BITMAPCONV_INFO::OuputFileHeader( const char * aBrdLayerName )
{ {
int Ypos = (int) ( m_PixmapHeight / 2 * m_ScaleY ); int Ypos = (int) ( m_PixmapHeight / 2 * m_ScaleY );
int fieldSize; // fields text size = 60 mils int fieldSize; // fields text size = 60 mils
...@@ -225,11 +257,10 @@ void BITMAPCONV_INFO::OuputFileHeader() ...@@ -225,11 +257,10 @@ void BITMAPCONV_INFO::OuputFileHeader()
// fields text thickness = 1.5 / 5 = 0.3mm // fields text thickness = 1.5 / 5 = 0.3mm
fprintf( m_Outfile, "(module %s (layer F.Cu)\n (at 0 0)\n", fprintf( m_Outfile, "(module %s (layer F.Cu)\n (at 0 0)\n",
m_CmpName ); m_CmpName );
fprintf( m_Outfile, " (fp_text reference \"G***\" (at 0 0) (layer F.SilkS) hide\n" fprintf( m_Outfile, " (fp_text reference \"G***\" (at 0 0) (layer %s) hide\n"
" (effects (font (thickness 0.3)))\n )\n" ); " (effects (font (thickness 0.3)))\n )\n", aBrdLayerName );
fprintf( m_Outfile, " (fp_text value \"%s\" (at 0.75 0) (layer F.SilkS) hide\n" fprintf( m_Outfile, " (fp_text value \"%s\" (at 0.75 0) (layer %s) hide\n"
" (effects (font (thickness 0.3)))\n )\n", " (effects (font (thickness 0.3)))\n )\n", m_CmpName, aBrdLayerName );
m_CmpName );
break; break;
case KICAD_LOGO: case KICAD_LOGO:
...@@ -283,7 +314,7 @@ void BITMAPCONV_INFO::OuputFileEnd() ...@@ -283,7 +314,7 @@ void BITMAPCONV_INFO::OuputFileEnd()
* write one polygon to output file. * write one polygon to output file.
* Polygon coordinates are expected scaled by the polygon extraction function * Polygon coordinates are expected scaled by the polygon extraction function
*/ */
void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon ) void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon, const char * aBrdLayerName )
{ {
unsigned ii, jj; unsigned ii, jj;
KPolyPoint currpoint; KPolyPoint currpoint;
...@@ -338,7 +369,9 @@ void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon ) ...@@ -338,7 +369,9 @@ void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon )
// Close polygon // Close polygon
fprintf( m_Outfile, " (xy %f %f) )", fprintf( m_Outfile, " (xy %f %f) )",
(startpoint.x() - offsetX) / 1e6, (startpoint.y() - offsetY) / 1e6 ); (startpoint.x() - offsetX) / 1e6, (startpoint.y() - offsetY) / 1e6 );
fprintf( m_Outfile, "(layer F.SilkS) (width %f)\n )\n", width );
fprintf( m_Outfile, "(layer %s) (width %f)\n )\n", aBrdLayerName, width );
} }
break; break;
...@@ -383,7 +416,7 @@ void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon ) ...@@ -383,7 +416,7 @@ void BITMAPCONV_INFO::OuputOnePolygon( KPolygon & aPolygon )
} }
void BITMAPCONV_INFO::CreateOutputFile() void BITMAPCONV_INFO::CreateOutputFile( BMP2CMP_MOD_LAYER aModLayer )
{ {
KPolyPoint currpoint; KPolyPoint currpoint;
...@@ -400,7 +433,10 @@ void BITMAPCONV_INFO::CreateOutputFile() ...@@ -400,7 +433,10 @@ void BITMAPCONV_INFO::CreateOutputFile()
setlocale( LC_NUMERIC, "C" ); // Switch the locale to standard C setlocale( LC_NUMERIC, "C" ); // Switch the locale to standard C
OuputFileHeader(); // The layer name has meaning only for .kicad_mod files.
// For these files the header creates 2 invisible texts: value and ref
// (needed but not usefull) on silk screen layer
OuputFileHeader( getBrdLayerName( MOD_LYR_FSILKS ) );
bool main_outline = true; bool main_outline = true;
...@@ -477,7 +513,7 @@ void BITMAPCONV_INFO::CreateOutputFile() ...@@ -477,7 +513,7 @@ void BITMAPCONV_INFO::CreateOutputFile()
for( unsigned ii = 0; ii < polyset_areas.size(); ii++ ) for( unsigned ii = 0; ii < polyset_areas.size(); ii++ )
{ {
KPolygon& poly = polyset_areas[ii]; KPolygon& poly = polyset_areas[ii];
OuputOnePolygon(poly ); OuputOnePolygon(poly, getBrdLayerName( aModLayer ) );
} }
polyset_areas.clear(); polyset_areas.clear();
......
...@@ -35,4 +35,13 @@ enum OUTPUT_FMT_ID ...@@ -35,4 +35,13 @@ enum OUTPUT_FMT_ID
FINAL_FMT = KICAD_LOGO FINAL_FMT = KICAD_LOGO
}; };
enum BMP2CMP_MOD_LAYER
{
MOD_LYR_FSILKS = 0,
MOD_LYR_FSOLDERMASK,
MOD_LYR_ECO1,
MOD_LYR_ECO2,
MOD_LYR_FINAL = MOD_LYR_ECO2
};
#endif // BITMAP2COMPONENT_H #endif // BITMAP2COMPONENT_H
...@@ -47,7 +47,6 @@ COMPONENTS_LISTBOX::~COMPONENTS_LISTBOX() ...@@ -47,7 +47,6 @@ COMPONENTS_LISTBOX::~COMPONENTS_LISTBOX()
BEGIN_EVENT_TABLE( COMPONENTS_LISTBOX, ITEMS_LISTBOX_BASE ) BEGIN_EVENT_TABLE( COMPONENTS_LISTBOX, ITEMS_LISTBOX_BASE )
EVT_SIZE( ITEMS_LISTBOX_BASE::OnSize )
EVT_CHAR( COMPONENTS_LISTBOX::OnChar ) EVT_CHAR( COMPONENTS_LISTBOX::OnChar )
EVT_LIST_ITEM_SELECTED( ID_CVPCB_COMPONENT_LIST, COMPONENTS_LISTBOX::OnSelectComponent ) EVT_LIST_ITEM_SELECTED( ID_CVPCB_COMPONENT_LIST, COMPONENTS_LISTBOX::OnSelectComponent )
END_EVENT_TABLE() END_EVENT_TABLE()
...@@ -72,14 +71,19 @@ void COMPONENTS_LISTBOX::SetString( unsigned linecount, const wxString& text ) ...@@ -72,14 +71,19 @@ void COMPONENTS_LISTBOX::SetString( unsigned linecount, const wxString& text )
linecount = m_ComponentList.Count() - 1; linecount = m_ComponentList.Count() - 1;
if( m_ComponentList.Count() > 0 ) if( m_ComponentList.Count() > 0 )
{
m_ComponentList[linecount] = text; m_ComponentList[linecount] = text;
UpdateWidth( linecount );
}
} }
void COMPONENTS_LISTBOX::AppendLine( const wxString& text ) void COMPONENTS_LISTBOX::AppendLine( const wxString& text )
{ {
m_ComponentList.Add( text ); m_ComponentList.Add( text );
SetItemCount( m_ComponentList.Count() ); int lines = m_ComponentList.Count();
SetItemCount( lines );
UpdateWidth( lines - 1 );
} }
......
...@@ -67,6 +67,7 @@ void FOOTPRINTS_LISTBOX::SetString( unsigned linecount, const wxString& text ) ...@@ -67,6 +67,7 @@ void FOOTPRINTS_LISTBOX::SetString( unsigned linecount, const wxString& text )
linecount = count - 1; linecount = count - 1;
m_footprintList[linecount] = text; m_footprintList[linecount] = text;
} }
UpdateWidth( linecount );
} }
...@@ -90,7 +91,9 @@ wxString FOOTPRINTS_LISTBOX::GetSelectedFootprint() ...@@ -90,7 +91,9 @@ wxString FOOTPRINTS_LISTBOX::GetSelectedFootprint()
void FOOTPRINTS_LISTBOX::AppendLine( const wxString& text ) void FOOTPRINTS_LISTBOX::AppendLine( const wxString& text )
{ {
m_footprintList.Add( text ); m_footprintList.Add( text );
SetItemCount( m_footprintList.Count() ); int lines = m_footprintList.Count();
SetItemCount( lines );
UpdateWidth( lines - 1 );
} }
...@@ -179,24 +182,12 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a ...@@ -179,24 +182,12 @@ void FOOTPRINTS_LISTBOX::SetFootprints( FOOTPRINT_LIST& aList, const wxString& a
SetItemCount( m_footprintList.GetCount() ); SetItemCount( m_footprintList.GetCount() );
SetSelection( selection, true ); SetSelection( selection, true );
RefreshItems( 0L, m_footprintList.GetCount()-1 ); RefreshItems( 0L, m_footprintList.GetCount()-1 );
UpdateWidth();
#if defined (__WXGTK__ ) //&& wxMINOR_VERSION == 8
// @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the
// column parameter is -1. This was the only way to prevent GTK3 from
// ellipsizing long strings down to a few characters. It still doesn't set
// the scroll bars correctly (too short) but it's better than any of the
// other alternatives. If someone knows how to fix this, please do.
SetColumnWidth( -1, wxLIST_AUTOSIZE );
#else
SetColumnWidth( 0, wxLIST_AUTOSIZE );
#endif
} }
} }
BEGIN_EVENT_TABLE( FOOTPRINTS_LISTBOX, ITEMS_LISTBOX_BASE ) BEGIN_EVENT_TABLE( FOOTPRINTS_LISTBOX, ITEMS_LISTBOX_BASE )
EVT_SIZE( ITEMS_LISTBOX_BASE::OnSize )
EVT_CHAR( FOOTPRINTS_LISTBOX::OnChar ) EVT_CHAR( FOOTPRINTS_LISTBOX::OnChar )
EVT_LIST_ITEM_SELECTED( ID_CVPCB_FOOTPRINT_LIST, FOOTPRINTS_LISTBOX::OnLeftClick ) EVT_LIST_ITEM_SELECTED( ID_CVPCB_FOOTPRINT_LIST, FOOTPRINTS_LISTBOX::OnLeftClick )
EVT_LIST_ITEM_ACTIVATED( ID_CVPCB_FOOTPRINT_LIST, FOOTPRINTS_LISTBOX::OnLeftDClick ) EVT_LIST_ITEM_ACTIVATED( ID_CVPCB_FOOTPRINT_LIST, FOOTPRINTS_LISTBOX::OnLeftDClick )
......
...@@ -66,6 +66,7 @@ void LIBRARY_LISTBOX::SetString( unsigned linecount, const wxString& text ) ...@@ -66,6 +66,7 @@ void LIBRARY_LISTBOX::SetString( unsigned linecount, const wxString& text )
if( linecount >= count ) if( linecount >= count )
linecount = count - 1; linecount = count - 1;
m_libraryList[linecount] = text; m_libraryList[linecount] = text;
UpdateWidth( linecount );
} }
} }
...@@ -87,7 +88,9 @@ wxString LIBRARY_LISTBOX::GetSelectedLibrary() ...@@ -87,7 +88,9 @@ wxString LIBRARY_LISTBOX::GetSelectedLibrary()
void LIBRARY_LISTBOX::AppendLine( const wxString& text ) void LIBRARY_LISTBOX::AppendLine( const wxString& text )
{ {
m_libraryList.Add( text ); m_libraryList.Add( text );
SetItemCount( m_libraryList.Count() ); int lines = m_libraryList.Count();
SetItemCount( lines );
UpdateWidth( lines - 1 );
} }
...@@ -129,23 +132,12 @@ void LIBRARY_LISTBOX::SetLibraryList( const wxArrayString& aList ) ...@@ -129,23 +132,12 @@ void LIBRARY_LISTBOX::SetLibraryList( const wxArrayString& aList )
if( m_libraryList.Count() ) if( m_libraryList.Count() )
{ {
RefreshItems( 0L, m_libraryList.Count()-1 ); RefreshItems( 0L, m_libraryList.Count()-1 );
UpdateWidth();
#if defined (__WXGTK__ ) && wxMINOR_VERSION == 8
// @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the
// column parameter is -1. This was the only way to prevent GTK3 from
// ellipsizing long strings down to a few characters. It still doesn't set
// the scroll bars correctly (too short) but it's better than any of the
// other alternatives. If someone knows how to fix this, please do.
SetColumnWidth( -1, wxLIST_AUTOSIZE );
#else
SetColumnWidth( 0, wxLIST_AUTOSIZE );
#endif
} }
} }
BEGIN_EVENT_TABLE( LIBRARY_LISTBOX, ITEMS_LISTBOX_BASE ) BEGIN_EVENT_TABLE( LIBRARY_LISTBOX, ITEMS_LISTBOX_BASE )
EVT_SIZE( ITEMS_LISTBOX_BASE::OnSize )
EVT_CHAR( LIBRARY_LISTBOX::OnChar ) EVT_CHAR( LIBRARY_LISTBOX::OnChar )
EVT_LIST_ITEM_SELECTED( ID_CVPCB_LIBRARY_LIST, LIBRARY_LISTBOX::OnSelectLibrary ) EVT_LIST_ITEM_SELECTED( ID_CVPCB_LIBRARY_LIST, LIBRARY_LISTBOX::OnSelectLibrary )
END_EVENT_TABLE() END_EVENT_TABLE()
......
...@@ -445,6 +445,10 @@ bool CVPCB_MAINFRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, i ...@@ -445,6 +445,10 @@ bool CVPCB_MAINFRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, i
UpdateTitle(); UpdateTitle();
// Resize the components list box. This is needed in case the
// contents have shrunk compared to the previous netlist.
m_compListBox->UpdateWidth();
// OSX need it since some objects are "rebuild" just make aware AUI // OSX need it since some objects are "rebuild" just make aware AUI
// Fixes #1258081 // Fixes #1258081
m_auimgr.Update(); m_auimgr.Update();
...@@ -949,17 +953,7 @@ void CVPCB_MAINFRAME::BuildCmpListBox() ...@@ -949,17 +953,7 @@ void CVPCB_MAINFRAME::BuildCmpListBox()
m_compListBox->SetItemCount( m_compListBox->m_ComponentList.Count() ); m_compListBox->SetItemCount( m_compListBox->m_ComponentList.Count() );
m_compListBox->SetSelection( 0, true ); m_compListBox->SetSelection( 0, true );
m_compListBox->RefreshItems( 0L, m_compListBox->m_ComponentList.Count()-1 ); m_compListBox->RefreshItems( 0L, m_compListBox->m_ComponentList.Count()-1 );
m_compListBox->UpdateWidth();
#if defined (__WXGTK__ )
// @bug On GTK and wxWidgets 2.8.x, this will assert in debug builds because the
// column parameter is -1. This was the only way to prevent GTK3 from
// ellipsizing long strings down to a few characters. It still doesn't set
// the scroll bars correctly (too short) but it's better than any of the
// other alternatives. If someone knows how to fix this, please do.
m_compListBox->SetColumnWidth( -1, wxLIST_AUTOSIZE );
#else
m_compListBox->SetColumnWidth( 0, wxLIST_AUTOSIZE );
#endif
} }
} }
......
...@@ -50,9 +50,23 @@ public: ...@@ -50,9 +50,23 @@ public:
~ITEMS_LISTBOX_BASE(); ~ITEMS_LISTBOX_BASE();
int GetSelection(); int GetSelection();
void OnSize( wxSizeEvent& event );
virtual CVPCB_MAINFRAME* GetParent() const; virtual CVPCB_MAINFRAME* GetParent() const;
/* Function UpdateWidth
*
* Update the width of the column based on its contents.
*
* @param aLine is the line to calculate the width from. If positive, the
* width will only be increased if needed. If negative, we start from
* scratch and all lines are considered, i.e., the column may be shrunk.
*/
void UpdateWidth( int aLine = -1 );
private:
void UpdateLineWidth( unsigned aLine );
int columnWidth;
}; };
......
...@@ -44,10 +44,9 @@ ...@@ -44,10 +44,9 @@
ITEMS_LISTBOX_BASE::ITEMS_LISTBOX_BASE( CVPCB_MAINFRAME* aParent, wxWindowID aId, ITEMS_LISTBOX_BASE::ITEMS_LISTBOX_BASE( CVPCB_MAINFRAME* aParent, wxWindowID aId,
const wxPoint& aLocation, const wxSize& aSize, const wxPoint& aLocation, const wxSize& aSize,
long aStyle) : long aStyle) :
wxListView( aParent, aId, aLocation, aSize, LISTB_STYLE | aStyle ) wxListView( aParent, aId, aLocation, aSize, LISTB_STYLE | aStyle ), columnWidth(0)
{ {
InsertColumn( 0, wxEmptyString ); InsertColumn( 0, wxEmptyString );
SetColumnWidth( 0, wxLIST_AUTOSIZE );
} }
...@@ -56,17 +55,47 @@ ITEMS_LISTBOX_BASE::~ITEMS_LISTBOX_BASE() ...@@ -56,17 +55,47 @@ ITEMS_LISTBOX_BASE::~ITEMS_LISTBOX_BASE()
} }
/* void ITEMS_LISTBOX_BASE::UpdateWidth( int aLine )
* Adjust the column width to the entire available window width
*/
void ITEMS_LISTBOX_BASE::OnSize( wxSizeEvent& event )
{ {
wxSize size = GetClientSize(); // Less than zero: recalculate width of all items.
int width = 0; if( aLine < 0 )
{
columnWidth = 0;
for( int ii = 0; ii < GetItemCount(); ii++ )
{
UpdateLineWidth( (unsigned)ii );
}
}
// Zero or above: update from a single line.
else
{
if( aLine < GetItemCount() )
UpdateLineWidth( (unsigned)aLine );
}
}
SetColumnWidth( 0, std::max( width, size.x ) );
event.Skip(); /*
* Calculate the width of the given line, and increase the column width
* if needed. This is effectively the wxListCtrl code for autosizing.
* NB. it relies on the caller checking the given line number is valid.
*/
void ITEMS_LISTBOX_BASE::UpdateLineWidth( unsigned aLine )
{
wxClientDC dc( this );
wxCoord w;
int newWidth = 10; // Value of AUTOSIZE_COL_MARGIN from wxWidgets source.
dc.SetFont( GetFont() );
dc.GetTextExtent( GetItemText( aLine, 0 ) + " ", &w, NULL );
newWidth += w;
if( newWidth > columnWidth )
{
columnWidth = newWidth;
SetColumnWidth( 0, columnWidth );
}
} }
......
...@@ -413,9 +413,11 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, ...@@ -413,9 +413,11 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) ); aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
bool fill = aPlotter->GetColorMode(); bool fill = aPlotter->GetColorMode();
// draw background for filled items using background option
// Solid lines will be drawn after the background
BOOST_FOREACH( LIB_ITEM& item, drawings ) BOOST_FOREACH( LIB_ITEM& item, drawings )
{ {
// Lib Fields not are plotted here, because this plot function // Lib Fields are not plotted here, because this plot function
// is used to plot schematic items, which have they own fields // is used to plot schematic items, which have they own fields
if( item.Type() == LIB_FIELD_T ) if( item.Type() == LIB_FIELD_T )
continue; continue;
...@@ -426,6 +428,24 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, ...@@ -426,6 +428,24 @@ void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) ) if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
continue; continue;
if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
item.Plot( aPlotter, aOffset, fill, aTransform );
}
// Not filled items and filled shapes are now plotted
// (plot only items which are not already plotted)
BOOST_FOREACH( LIB_ITEM& item, drawings )
{
if( item.Type() == LIB_FIELD_T )
continue;
if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
continue;
if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
continue;
if( item.m_Fill != FILLED_WITH_BG_BODYCOLOR )
item.Plot( aPlotter, aOffset, fill, aTransform ); item.Plot( aPlotter, aOffset, fill, aTransform );
} }
} }
......
...@@ -37,7 +37,6 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID ...@@ -37,7 +37,6 @@ DIALOG_LABEL_EDITOR_BASE::DIALOG_LABEL_EDITOR_BASE( wxWindow* parent, wxWindowID
bSizeText->Add( m_textLabelSingleLine, 0, wxEXPAND|wxLEFT, 3 ); bSizeText->Add( m_textLabelSingleLine, 0, wxEXPAND|wxLEFT, 3 );
m_textLabelMultiLine = new wxTextCtrl( this, wxID_VALUEMULTI, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_PROCESS_ENTER ); m_textLabelMultiLine = new wxTextCtrl( this, wxID_VALUEMULTI, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_PROCESS_ENTER );
m_textLabelMultiLine->SetMaxLength( 0 );
m_textLabelMultiLine->SetMinSize( wxSize( -1,60 ) ); m_textLabelMultiLine->SetMinSize( wxSize( -1,60 ) );
bSizeText->Add( m_textLabelMultiLine, 1, wxEXPAND|wxLEFT, 3 ); bSizeText->Add( m_textLabelMultiLine, 1, wxEXPAND|wxLEFT, 3 );
......
...@@ -327,7 +327,7 @@ ...@@ -327,7 +327,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size">-1,60</property> <property name="minimum_size">-1,60</property>
......
...@@ -80,7 +80,6 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin ...@@ -80,7 +80,6 @@ DIALOG_ERC_BASE::DIALOG_ERC_BASE( wxWindow* parent, wxWindowID id, const wxStrin
bSizerMessages->Add( m_titleMessages, 0, wxRIGHT|wxLEFT, 5 ); bSizerMessages->Add( m_titleMessages, 0, wxRIGHT|wxLEFT, 5 );
m_MessagesList = new wxTextCtrl( m_PanelERC, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); m_MessagesList = new wxTextCtrl( m_PanelERC, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_MessagesList->SetMaxLength( 0 );
bSizerMessages->Add( m_MessagesList, 1, wxEXPAND|wxLEFT, 5 ); bSizerMessages->Add( m_MessagesList, 1, wxEXPAND|wxLEFT, 5 );
......
...@@ -1032,7 +1032,7 @@ ...@@ -1032,7 +1032,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size">-1,-1</property> <property name="minimum_size">-1,-1</property>
......
...@@ -146,7 +146,6 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind ...@@ -146,7 +146,6 @@ DIALOG_PLOT_SCHEMATIC_BASE::DIALOG_PLOT_SCHEMATIC_BASE( wxWindow* parent, wxWind
bSizer4->Add( m_staticText2, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bSizer4->Add( m_staticText2, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_MessagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); m_MessagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
m_MessagesBox->SetMaxLength( 0 );
m_MessagesBox->SetMinSize( wxSize( -1,80 ) ); m_MessagesBox->SetMinSize( wxSize( -1,80 ) );
bSizer4->Add( m_MessagesBox, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); bSizer4->Add( m_MessagesBox, 1, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
......
...@@ -1799,7 +1799,7 @@ ...@@ -1799,7 +1799,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size">-1,80</property> <property name="minimum_size">-1,80</property>
......
=== added file 'patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch' === modified file 'patches/wxwidgets-3.0.2_macosx_yosemite.patch'
--- patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch 1970-01-01 00:00:00 +0000 --- patches/wxwidgets-3.0.2_macosx_yosemite.patch 2014-11-04 19:24:22 +0000
+++ patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch 2014-10-29 18:17:55 +0000 +++ patches/wxwidgets-3.0.2_macosx_yosemite.patch 2014-11-12 01:54:50 +0000
@@ -0,0 +1,11 @@ @@ -1,15 +1,11 @@
-=== added file 'patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch'
---- patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch 1970-01-01 00:00:00 +0000
-+++ patches/wxwidgets-3.0.2_macosx_yosemite_webview_webkit.mm.patch 2014-10-29 18:17:55 +0000
-@@ -0,0 +1,11 @@
-+--- src/osx/webview_webkit.mm.orig 2014-09-16 07:27:52.000000000 -0600
-++++ src/osx/webview_webkit.mm 2014-09-16 07:28:12.000000000 -0600
-+@@ -28,7 +28,7 @@
-+ #include "wx/hashmap.h"
-+ #include "wx/filesys.h"
-+
-+-#include <WebKit/WebKit.h>
-++#include <WebKit/WebKitLegacy.h>
-+ #include <WebKit/HIWebView.h>
-+ #include <WebKit/CarbonUtils.h>
-+
+--- src/osx/webview_webkit.mm.orig 2014-09-16 07:27:52.000000000 -0600 +--- src/osx/webview_webkit.mm.orig 2014-09-16 07:27:52.000000000 -0600
++++ src/osx/webview_webkit.mm 2014-09-16 07:28:12.000000000 -0600 ++++ src/osx/webview_webkit.mm 2014-09-16 07:28:12.000000000 -0600
+@@ -28,7 +28,7 @@ +@@ -28,7 +28,7 @@
...@@ -13,3 +28,4 @@ ...@@ -13,3 +28,4 @@
+ #include <WebKit/HIWebView.h> + #include <WebKit/HIWebView.h>
+ #include <WebKit/CarbonUtils.h> + #include <WebKit/CarbonUtils.h>
+ +
...@@ -1140,7 +1140,6 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow ...@@ -1140,7 +1140,6 @@ PCB_CALCULATOR_FRAME_BASE::PCB_CALCULATOR_FRAME_BASE( wxWindow* parent, wxWindow
bMiddleSizerAtt->Add( m_staticTextAttMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bMiddleSizerAtt->Add( m_staticTextAttMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_Attenuator_Messages = new wxTextCtrl( m_panelAttenuators, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); m_Attenuator_Messages = new wxTextCtrl( m_panelAttenuators, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_Attenuator_Messages->SetMaxLength( 0 );
bMiddleSizerAtt->Add( m_Attenuator_Messages, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); bMiddleSizerAtt->Add( m_Attenuator_Messages, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
......
...@@ -16799,7 +16799,7 @@ ...@@ -16799,7 +16799,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size"></property> <property name="minimum_size"></property>
...@@ -87,7 +87,6 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi ...@@ -87,7 +87,6 @@ DIALOG_EXCHANGE_MODULE_BASE::DIALOG_EXCHANGE_MODULE_BASE( wxWindow* parent, wxWi
bMainSizer->Add( m_staticTextMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bMainSizer->Add( m_staticTextMsg, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_WinMessages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); m_WinMessages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_WinMessages->SetMaxLength( 0 );
m_WinMessages->SetMinSize( wxSize( 450,300 ) ); m_WinMessages->SetMinSize( wxSize( 450,300 ) );
bMainSizer->Add( m_WinMessages, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); bMainSizer->Add( m_WinMessages, 1, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
......
...@@ -1219,7 +1219,7 @@ ...@@ -1219,7 +1219,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size">450,300</property> <property name="minimum_size">450,300</property>
......
...@@ -26,7 +26,6 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare ...@@ -26,7 +26,6 @@ DIALOG_PCB_TEXT_PROPERTIES_BASE::DIALOG_PCB_TEXT_PROPERTIES_BASE( wxWindow* pare
bSizer9->Add( m_TextLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); bSizer9->Add( m_TextLabel, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
m_TextContentCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); m_TextContentCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
m_TextContentCtrl->SetMaxLength( 0 );
m_TextContentCtrl->SetToolTip( _("Enter the text placed on selected layer.") ); m_TextContentCtrl->SetToolTip( _("Enter the text placed on selected layer.") );
m_TextContentCtrl->SetMinSize( wxSize( 400,60 ) ); m_TextContentCtrl->SetMinSize( wxSize( 400,60 ) );
......
...@@ -218,7 +218,7 @@ ...@@ -218,7 +218,7 @@
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
<property name="maxlength">0</property> <property name="maxlength"></property>
<property name="min_size"></property> <property name="min_size"></property>
<property name="minimize_button">0</property> <property name="minimize_button">0</property>
<property name="minimum_size">400,60</property> <property name="minimum_size">400,60</property>
......
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 6.1.3a * * Version : 6.2.1 *
* Date : 22 January 2014 * * Date : 31 October 2014 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2014 * * Copyright : Angus Johnson 2010-2014 *
* * * *
...@@ -50,15 +50,6 @@ ...@@ -50,15 +50,6 @@
namespace ClipperLib { namespace ClipperLib {
#ifdef use_int32
static cInt const loRange = 46340;
static cInt const hiRange = 46340;
#else
static cInt const loRange = 0x3FFFFFFF;
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
typedef unsigned long long ulong64;
#endif
static double const pi = 3.141592653589793238; static double const pi = 3.141592653589793238;
static double const two_pi = pi *2; static double const two_pi = pi *2;
static double const def_arc_tolerance = 0.25; static double const def_arc_tolerance = 0.25;
...@@ -99,11 +90,10 @@ struct IntersectNode { ...@@ -99,11 +90,10 @@ struct IntersectNode {
IntPoint Pt; IntPoint Pt;
}; };
struct LocalMinima { struct LocalMinimum {
cInt Y; cInt Y;
TEdge *LeftBound; TEdge *LeftBound;
TEdge *RightBound; TEdge *RightBound;
LocalMinima *Next;
}; };
struct OutPt; struct OutPt;
...@@ -131,6 +121,14 @@ struct Join { ...@@ -131,6 +121,14 @@ struct Join {
IntPoint OffPt; IntPoint OffPt;
}; };
struct LocMinSorter
{
inline bool operator()(const LocalMinimum& locMin1, const LocalMinimum& locMin2)
{
return locMin2.Y < locMin1.Y;
}
};
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -170,7 +168,10 @@ PolyNode* PolyTree::GetFirst() const ...@@ -170,7 +168,10 @@ PolyNode* PolyTree::GetFirst() const
int PolyTree::Total() const int PolyTree::Total() const
{ {
return (int)AllNodes.size(); int result = (int)AllNodes.size();
//with negative offsets, ignore the hidden outer polygon ...
if (result > 0 && Childs[0] != AllNodes[0]) result--;
return result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -240,8 +241,8 @@ bool PolyNode::IsOpen() const ...@@ -240,8 +241,8 @@ bool PolyNode::IsOpen() const
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Int128 class (enables safe math on signed 64bit integers) // Int128 class (enables safe math on signed 64bit integers)
// eg Int128 val1((cInt)9223372036854775807); //ie 2^63 -1 // eg Int128 val1((long64)9223372036854775807); //ie 2^63 -1
// Int128 val2((cInt)9223372036854775807); // Int128 val2((long64)9223372036854775807);
// Int128 val3 = val1 * val2; // Int128 val3 = val1 * val2;
// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37) // val3.AsString => "85070591730234615847396907784232501249" (8.5e+37)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -249,22 +250,21 @@ bool PolyNode::IsOpen() const ...@@ -249,22 +250,21 @@ bool PolyNode::IsOpen() const
class Int128 class Int128
{ {
public: public:
ulong64 lo;
long64 hi;
cUInt lo; Int128(long64 _lo = 0)
cInt hi;
Int128(cInt _lo = 0)
{ {
lo = (cUInt)_lo; lo = (ulong64)_lo;
if (_lo < 0) hi = -1; else hi = 0; if (_lo < 0) hi = -1; else hi = 0;
} }
Int128(const Int128 &val): lo(val.lo), hi(val.hi){} Int128(const Int128 &val): lo(val.lo), hi(val.hi){}
Int128(const cInt& _hi, const ulong64& _lo): lo(_lo), hi(_hi){} Int128(const long64& _hi, const ulong64& _lo): lo(_lo), hi(_hi){}
Int128& operator = (const cInt &val) Int128& operator = (const long64 &val)
{ {
lo = (ulong64)val; lo = (ulong64)val;
if (val < 0) hi = -1; else hi = 0; if (val < 0) hi = -1; else hi = 0;
...@@ -330,81 +330,18 @@ class Int128 ...@@ -330,81 +330,18 @@ class Int128
Int128 operator-() const //unary negation Int128 operator-() const //unary negation
{ {
if (lo == 0) if (lo == 0)
return Int128(-hi,0); return Int128(-hi, 0);
else else
return Int128(~hi,~lo +1); return Int128(~hi, ~lo + 1);
} }
Int128 operator/ (const Int128 &rhs) const operator double() const
{
if (rhs.lo == 0 && rhs.hi == 0)
throw "Int128 operator/: divide by zero";
bool negate = (rhs.hi < 0) != (hi < 0);
Int128 dividend = *this;
Int128 divisor = rhs;
if (dividend.hi < 0) dividend = -dividend;
if (divisor.hi < 0) divisor = -divisor;
if (divisor < dividend)
{
Int128 result = Int128(0);
Int128 cntr = Int128(1);
while (divisor.hi >= 0 && !(divisor > dividend))
{
divisor.hi <<= 1;
if ((cInt)divisor.lo < 0) divisor.hi++;
divisor.lo <<= 1;
cntr.hi <<= 1;
if ((cInt)cntr.lo < 0) cntr.hi++;
cntr.lo <<= 1;
}
divisor.lo >>= 1;
if ((divisor.hi & 1) == 1)
divisor.lo |= 0x8000000000000000LL;
divisor.hi = (ulong64)divisor.hi >> 1;
cntr.lo >>= 1;
if ((cntr.hi & 1) == 1)
cntr.lo |= 0x8000000000000000LL;
cntr.hi >>= 1;
while (cntr.hi != 0 || cntr.lo != 0)
{
if (!(dividend < divisor))
{
dividend -= divisor;
result.hi |= cntr.hi;
result.lo |= cntr.lo;
}
divisor.lo >>= 1;
if ((divisor.hi & 1) == 1)
divisor.lo |= 0x8000000000000000LL;
divisor.hi >>= 1;
cntr.lo >>= 1;
if ((cntr.hi & 1) == 1)
cntr.lo |= 0x8000000000000000LL;
cntr.hi >>= 1;
}
if (negate) result = -result;
return result;
}
else if (rhs.hi == this->hi && rhs.lo == this->lo)
return Int128(negate ? -1: 1);
else
return Int128(0);
}
double AsDouble() const
{ {
const double shift64 = 18446744073709551616.0; //2^64 const double shift64 = 18446744073709551616.0; //2^64
if (hi < 0) if (hi < 0)
{ {
cUInt lo_ = ~lo + 1; if (lo == 0) return (double)hi * shift64;
if (lo_ == 0) return (double)hi * shift64; else return -(double)(~lo + ~hi * shift64);
else return -(double)(lo_ + ~hi * shift64);
} }
else else
return (double)(lo + hi * shift64); return (double)(lo + hi * shift64);
...@@ -413,7 +350,7 @@ class Int128 ...@@ -413,7 +350,7 @@ class Int128
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
Int128 Int128Mul (cInt lhs, cInt rhs) Int128 Int128Mul (long64 lhs, long64 rhs)
{ {
bool negate = (lhs < 0) != (rhs < 0); bool negate = (lhs < 0) != (rhs < 0);
...@@ -431,9 +368,9 @@ Int128 Int128Mul (cInt lhs, cInt rhs) ...@@ -431,9 +368,9 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi; ulong64 c = int1Hi * int2Lo + int1Lo * int2Hi;
Int128 tmp; Int128 tmp;
tmp.hi = cInt(a + (c >> 32)); tmp.hi = long64(a + (c >> 32));
tmp.lo = cInt(c << 32); tmp.lo = long64(c << 32);
tmp.lo += cInt(b); tmp.lo += long64(b);
if (tmp.lo < b) tmp.hi++; if (tmp.lo < b) tmp.hi++;
if (negate) tmp = -tmp; if (negate) tmp = -tmp;
return tmp; return tmp;
...@@ -444,6 +381,13 @@ Int128 Int128Mul (cInt lhs, cInt rhs) ...@@ -444,6 +381,13 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
// Miscellaneous global functions // Miscellaneous global functions
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Swap(cInt& val1, cInt& val2)
{
cInt tmp = val1;
val1 = val2;
val2 = tmp;
}
//------------------------------------------------------------------------------
bool Orientation(const Path &poly) bool Orientation(const Path &poly)
{ {
return Area(poly) >= 0; return Area(poly) >= 0;
...@@ -494,6 +438,7 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp) ...@@ -494,6 +438,7 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
int PointInPolygon (const IntPoint &pt, const Path &path) int PointInPolygon (const IntPoint &pt, const Path &path)
{ {
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf //http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int result = 0; int result = 0;
size_t cnt = path.size(); size_t cnt = path.size();
...@@ -539,7 +484,6 @@ int PointInPolygon (const IntPoint &pt, const Path &path) ...@@ -539,7 +484,6 @@ int PointInPolygon (const IntPoint &pt, const Path &path)
int PointInPolygon (const IntPoint &pt, OutPt *op) int PointInPolygon (const IntPoint &pt, OutPt *op)
{ {
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary //returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int result = 0; int result = 0;
OutPt* startOp = op; OutPt* startOp = op;
for(;;) for(;;)
...@@ -584,8 +528,9 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) ...@@ -584,8 +528,9 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
OutPt* op = OutPt1; OutPt* op = OutPt1;
do do
{ {
//nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
int res = PointInPolygon(op->Pt, OutPt2); int res = PointInPolygon(op->Pt, OutPt2);
if (res >= 0) return res != 0; if (res >= 0) return res > 0;
op = op->Next; op = op->Next;
} }
while (op != OutPt1); while (op != OutPt1);
...@@ -674,20 +619,18 @@ inline cInt TopX(TEdge &edge, const cInt currentY) ...@@ -674,20 +619,18 @@ inline cInt TopX(TEdge &edge, const cInt currentY)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool IntersectPoint(TEdge &Edge1, TEdge &Edge2, void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip)
IntPoint &ip, bool UseFullInt64Range)
{ {
#ifdef use_xyz #ifdef use_xyz
ip.Z = 0; ip.Z = 0;
#endif #endif
double b1, b2; double b1, b2;
//nb: with very large coordinate values, it's possible for SlopesEqual() to if (Edge1.Dx == Edge2.Dx)
//return false but for the edge.Dx value be equal due to double precision rounding.
if (SlopesEqual(Edge1, Edge2, UseFullInt64Range) || Edge1.Dx == Edge2.Dx)
{ {
if (Edge2.Bot.Y > Edge1.Bot.Y) ip = Edge2.Bot; ip.Y = Edge1.Curr.Y;
else ip = Edge1.Bot; ip.X = TopX(Edge1, ip.Y);
return false; return;
} }
else if (Edge1.Delta.X == 0) else if (Edge1.Delta.X == 0)
{ {
...@@ -734,7 +677,15 @@ bool IntersectPoint(TEdge &Edge1, TEdge &Edge2, ...@@ -734,7 +677,15 @@ bool IntersectPoint(TEdge &Edge1, TEdge &Edge2,
else else
ip.X = TopX(Edge2, ip.Y); ip.X = TopX(Edge2, ip.Y);
} }
return true; //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ...
if (ip.Y > Edge1.Curr.Y)
{
ip.Y = Edge1.Curr.Y;
//use the more vertical edge to derive X ...
if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx))
ip.X = TopX(Edge2, ip.Y); else
ip.X = TopX(Edge1, ip.Y);
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -807,13 +758,9 @@ inline void ReverseHorizontal(TEdge &e) ...@@ -807,13 +758,9 @@ inline void ReverseHorizontal(TEdge &e)
//swap horizontal edges' Top and Bottom x's so they follow the natural //swap horizontal edges' Top and Bottom x's so they follow the natural
//progression of the bounds - ie so their xbots will align with the //progression of the bounds - ie so their xbots will align with the
//adjoining lower edge. [Helpful in the ProcessHorizontal() method.] //adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
cInt tmp = e.Top.X; Swap(e.Top.X, e.Bot.X);
e.Top.X = e.Bot.X;
e.Bot.X = tmp;
#ifdef use_xyz #ifdef use_xyz
tmp = e.Top.Z; Swap(e.Top.Z, e.Bot.Z);
e.Top.Z = e.Bot.Z;
e.Bot.Z = tmp;
#endif #endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -905,26 +852,6 @@ OutPt* GetBottomPt(OutPt *pp) ...@@ -905,26 +852,6 @@ OutPt* GetBottomPt(OutPt *pp)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool FindSegment(OutPt* &pp, bool UseFullInt64Range,
IntPoint &pt1, IntPoint &pt2)
{
//OutPt1 & OutPt2 => the overlap segment (if the function returns true)
if (!pp) return false;
OutPt* pp2 = pp;
IntPoint pt1a = pt1, pt2a = pt2;
do
{
if (SlopesEqual(pt1a, pt2a, pp->Pt, pp->Prev->Pt, UseFullInt64Range) &&
SlopesEqual(pt1a, pt2a, pp->Pt, UseFullInt64Range) &&
GetOverlapSegment(pt1a, pt2a, pp->Pt, pp->Prev->Pt, pt1, pt2))
return true;
pp = pp->Next;
}
while (pp != pp2);
return false;
}
//------------------------------------------------------------------------------
bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
const IntPoint pt2, const IntPoint pt3) const IntPoint pt2, const IntPoint pt3)
{ {
...@@ -937,50 +864,20 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1, ...@@ -937,50 +864,20 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
OutPt* InsertPolyPtBetween(OutPt* p1, OutPt* p2, const IntPoint Pt) bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b)
{
if (p1 == p2) throw "JoinError";
OutPt* result = new OutPt;
result->Pt = Pt;
if (p2 == p1->Next)
{
p1->Next = result;
p2->Prev = result;
result->Next = p2;
result->Prev = p1;
} else
{
p2->Next = result;
p1->Prev = result;
result->Next = p1;
result->Prev = p2;
}
return result;
}
//------------------------------------------------------------------------------
bool HorzSegmentsOverlap(const IntPoint& pt1a, const IntPoint& pt1b,
const IntPoint& pt2a, const IntPoint& pt2b)
{ {
//precondition: both segments are horizontal if (seg1a > seg1b) Swap(seg1a, seg1b);
if ((pt1a.X > pt2a.X) == (pt1a.X < pt2b.X)) return true; if (seg2a > seg2b) Swap(seg2a, seg2b);
else if ((pt1b.X > pt2a.X) == (pt1b.X < pt2b.X)) return true; return (seg1a < seg2b) && (seg2a < seg1b);
else if ((pt2a.X > pt1a.X) == (pt2a.X < pt1b.X)) return true;
else if ((pt2b.X > pt1a.X) == (pt2b.X < pt1b.X)) return true;
else if ((pt1a.X == pt2a.X) && (pt1b.X == pt2b.X)) return true;
else if ((pt1a.X == pt2b.X) && (pt1b.X == pt2a.X)) return true;
else return false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// ClipperBase class methods ... // ClipperBase class methods ...
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
ClipperBase::ClipperBase() //constructor ClipperBase::ClipperBase() //constructor
{ {
m_MinimaList = 0; m_CurrentLM = m_MinimaList.begin(); //begin() == end() here
m_CurrentLM = 0;
m_UseFullRange = false; m_UseFullRange = false;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1023,23 +920,76 @@ TEdge* FindNextLocMin(TEdge* E) ...@@ -1023,23 +920,76 @@ TEdge* FindNextLocMin(TEdge* E)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
{ {
TEdge *EStart = E, *Result = E; TEdge *Result = E;
TEdge *Horz = 0; TEdge *Horz = 0;
cInt StartX;
if (IsHorizontal(*E)) if (E->OutIdx == Skip)
{ {
//it's possible for adjacent overlapping horz edges to start heading left //if edges still remain in the current bound beyond the skip edge then
//before finishing right, so ... //create another LocMin and call ProcessBound once more
if (IsClockwise) StartX = E->Prev->Bot.X; if (NextIsForward)
else StartX = E->Next->Bot.X; {
if (E->Bot.X != StartX) ReverseHorizontal(*E); while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
//don't include top horizontals when parsing a bound a second time,
//they will be contained in the opposite bound ...
while (E != Result && IsHorizontal(*E)) E = E->Prev;
}
else
{
while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
while (E != Result && IsHorizontal(*E)) E = E->Next;
} }
if (Result->OutIdx != Skip) if (E == Result)
{ {
if (IsClockwise) if (NextIsForward) Result = E->Next;
else Result = E->Prev;
}
else
{
//there are more edges in the bound beyond result starting with E
if (NextIsForward)
E = Result->Next;
else
E = Result->Prev;
MinimaList::value_type locMin;
locMin.Y = E->Bot.Y;
locMin.LeftBound = 0;
locMin.RightBound = E;
E->WindDelta = 0;
Result = ProcessBound(E, NextIsForward);
m_MinimaList.push_back(locMin);
}
return Result;
}
TEdge *EStart;
if (IsHorizontal(*E))
{
//We need to be careful with open paths because this may not be a
//true local minima (ie E may be following a skip edge).
//Also, consecutive horz. edges may start heading left before going right.
if (NextIsForward)
EStart = E->Prev;
else
EStart = E->Next;
if (EStart->OutIdx != Skip)
{
if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge
{
if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X)
ReverseHorizontal(*E);
}
else if (EStart->Bot.X != E->Bot.X)
ReverseHorizontal(*E);
}
}
EStart = E;
if (NextIsForward)
{ {
while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip)
Result = Result->Next; Result = Result->Next;
...@@ -1052,7 +1002,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) ...@@ -1052,7 +1002,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev;
if (Horz->Prev->Top.X == Result->Next->Top.X) if (Horz->Prev->Top.X == Result->Next->Top.X)
{ {
if (!IsClockwise) Result = Horz->Prev; if (!NextIsForward) Result = Horz->Prev;
} }
else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; else if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev;
} }
...@@ -1076,7 +1026,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) ...@@ -1076,7 +1026,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; while (IsHorizontal(*Horz->Next)) Horz = Horz->Next;
if (Horz->Next->Top.X == Result->Prev->Top.X) if (Horz->Next->Top.X == Result->Prev->Top.X)
{ {
if (!IsClockwise) Result = Horz->Next; if (!NextIsForward) Result = Horz->Next;
} }
else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; else if (Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next;
} }
...@@ -1092,45 +1042,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise) ...@@ -1092,45 +1042,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
ReverseHorizontal(*E); ReverseHorizontal(*E);
Result = Result->Prev; //move to the edge just beyond current bound Result = Result->Prev; //move to the edge just beyond current bound
} }
}
if (Result->OutIdx == Skip)
{
//if edges still remain in the current bound beyond the skip edge then
//create another LocMin and call ProcessBound once more
E = Result;
if (IsClockwise)
{
while (E->Top.Y == E->Next->Bot.Y) E = E->Next;
//don't include top horizontals when parsing a bound a second time,
//they will be contained in the opposite bound ...
while (E != Result && IsHorizontal(*E)) E = E->Prev;
} else
{
while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev;
while (E != Result && IsHorizontal(*E)) E = E->Next;
}
if (E == Result)
{
if (IsClockwise) Result = E->Next;
else Result = E->Prev;
} else
{
//there are more edges in the bound beyond result starting with E
if (IsClockwise)
E = Result->Next;
else
E = Result->Prev;
LocalMinima* locMin = new LocalMinima;
locMin->Next = 0;
locMin->Y = E->Bot.Y;
locMin->LeftBound = 0;
locMin->RightBound = E;
locMin->RightBound->WindDelta = 0;
Result = ProcessBound(locMin->RightBound, IsClockwise);
InsertLocalMinima(locMin);
}
}
return Result; return Result;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1179,7 +1091,8 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) ...@@ -1179,7 +1091,8 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
TEdge *E = eStart, *eLoopStop = eStart; TEdge *E = eStart, *eLoopStop = eStart;
for (;;) for (;;)
{ {
if ((E->Curr == E->Next->Curr)) //nb: allows matching start and end points when not Closed ...
if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart))
{ {
if (E == E->Next) break; if (E == E->Next) break;
if (E == eStart) eStart = E->Next; if (E == eStart) eStart = E->Next;
...@@ -1205,7 +1118,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) ...@@ -1205,7 +1118,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
continue; continue;
} }
E = E->Next; E = E->Next;
if (E == eLoopStop) break; if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break;
} }
if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next)))
...@@ -1243,27 +1156,31 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) ...@@ -1243,27 +1156,31 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
} }
E->Prev->OutIdx = Skip; E->Prev->OutIdx = Skip;
if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev); if (E->Prev->Bot.X < E->Prev->Top.X) ReverseHorizontal(*E->Prev);
LocalMinima* locMin = new LocalMinima(); MinimaList::value_type locMin;
locMin->Next = 0; locMin.Y = E->Bot.Y;
locMin->Y = E->Bot.Y; locMin.LeftBound = 0;
locMin->LeftBound = 0; locMin.RightBound = E;
locMin->RightBound = E; locMin.RightBound->Side = esRight;
locMin->RightBound->Side = esRight; locMin.RightBound->WindDelta = 0;
locMin->RightBound->WindDelta = 0;
while (E->Next->OutIdx != Skip) while (E->Next->OutIdx != Skip)
{ {
E->NextInLML = E->Next; E->NextInLML = E->Next;
if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E);
E = E->Next; E = E->Next;
} }
InsertLocalMinima(locMin); m_MinimaList.push_back(locMin);
m_edges.push_back(edges); m_edges.push_back(edges);
return true; return true;
} }
m_edges.push_back(edges); m_edges.push_back(edges);
bool clockwise; bool leftBoundIsForward;
TEdge* EMin = 0; TEdge* EMin = 0;
//workaround to avoid an endless loop in the while loop below when
//open paths have matching start and end points ...
if (E->Prev->Bot == E->Prev->Top) E = E->Next;
for (;;) for (;;)
{ {
E = FindNextLocMin(E); E = FindNextLocMin(E);
...@@ -1272,38 +1189,40 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) ...@@ -1272,38 +1189,40 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
//E and E.Prev now share a local minima (left aligned if horizontal). //E and E.Prev now share a local minima (left aligned if horizontal).
//Compare their slopes to find which starts which bound ... //Compare their slopes to find which starts which bound ...
LocalMinima* locMin = new LocalMinima; MinimaList::value_type locMin;
locMin->Next = 0; locMin.Y = E->Bot.Y;
locMin->Y = E->Bot.Y;
if (E->Dx < E->Prev->Dx) if (E->Dx < E->Prev->Dx)
{ {
locMin->LeftBound = E->Prev; locMin.LeftBound = E->Prev;
locMin->RightBound = E; locMin.RightBound = E;
clockwise = false; //Q.nextInLML = Q.prev leftBoundIsForward = false; //Q.nextInLML = Q.prev
} else } else
{ {
locMin->LeftBound = E; locMin.LeftBound = E;
locMin->RightBound = E->Prev; locMin.RightBound = E->Prev;
clockwise = true; //Q.nextInLML = Q.next leftBoundIsForward = true; //Q.nextInLML = Q.next
} }
locMin->LeftBound->Side = esLeft; locMin.LeftBound->Side = esLeft;
locMin->RightBound->Side = esRight; locMin.RightBound->Side = esRight;
if (!Closed) locMin->LeftBound->WindDelta = 0; if (!Closed) locMin.LeftBound->WindDelta = 0;
else if (locMin->LeftBound->Next == locMin->RightBound) else if (locMin.LeftBound->Next == locMin.RightBound)
locMin->LeftBound->WindDelta = -1; locMin.LeftBound->WindDelta = -1;
else locMin->LeftBound->WindDelta = 1; else locMin.LeftBound->WindDelta = 1;
locMin->RightBound->WindDelta = -locMin->LeftBound->WindDelta; locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta;
E = ProcessBound(locMin->LeftBound, clockwise); E = ProcessBound(locMin.LeftBound, leftBoundIsForward);
TEdge* E2 = ProcessBound(locMin->RightBound, !clockwise); if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward);
if (locMin->LeftBound->OutIdx == Skip) TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward);
locMin->LeftBound = 0; if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward);
else if (locMin->RightBound->OutIdx == Skip)
locMin->RightBound = 0; if (locMin.LeftBound->OutIdx == Skip)
InsertLocalMinima(locMin); locMin.LeftBound = 0;
if (!clockwise) E = E2; else if (locMin.RightBound->OutIdx == Skip)
locMin.RightBound = 0;
m_MinimaList.push_back(locMin);
if (!leftBoundIsForward) E = E2;
} }
return true; return true;
} }
...@@ -1318,27 +1237,6 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) ...@@ -1318,27 +1237,6 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void ClipperBase::InsertLocalMinima(LocalMinima *newLm)
{
if( ! m_MinimaList )
{
m_MinimaList = newLm;
}
else if( newLm->Y >= m_MinimaList->Y )
{
newLm->Next = m_MinimaList;
m_MinimaList = newLm;
} else
{
LocalMinima* tmpLm = m_MinimaList;
while( tmpLm->Next && ( newLm->Y < tmpLm->Next->Y ) )
tmpLm = tmpLm->Next;
newLm->Next = tmpLm->Next;
tmpLm->Next = newLm;
}
}
//------------------------------------------------------------------------------
void ClipperBase::Clear() void ClipperBase::Clear()
{ {
DisposeLocalMinimaList(); DisposeLocalMinimaList();
...@@ -1357,12 +1255,12 @@ void ClipperBase::Clear() ...@@ -1357,12 +1255,12 @@ void ClipperBase::Clear()
void ClipperBase::Reset() void ClipperBase::Reset()
{ {
m_CurrentLM = m_MinimaList; m_CurrentLM = m_MinimaList.begin();
if( !m_CurrentLM ) return; //ie nothing to process if (m_CurrentLM == m_MinimaList.end()) return; //ie nothing to process
std::sort(m_MinimaList.begin(), m_MinimaList.end(), LocMinSorter());
//reset all edges ... //reset all edges ...
LocalMinima* lm = m_MinimaList; for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
while( lm )
{ {
TEdge* e = lm->LeftBound; TEdge* e = lm->LeftBound;
if (e) if (e)
...@@ -1379,35 +1277,29 @@ void ClipperBase::Reset() ...@@ -1379,35 +1277,29 @@ void ClipperBase::Reset()
e->Side = esRight; e->Side = esRight;
e->OutIdx = Unassigned; e->OutIdx = Unassigned;
} }
lm = lm->Next;
} }
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void ClipperBase::DisposeLocalMinimaList() void ClipperBase::DisposeLocalMinimaList()
{ {
while( m_MinimaList ) m_MinimaList.clear();
{ m_CurrentLM = m_MinimaList.begin();
LocalMinima* tmpLm = m_MinimaList->Next;
delete m_MinimaList;
m_MinimaList = tmpLm;
}
m_CurrentLM = 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void ClipperBase::PopLocalMinima() void ClipperBase::PopLocalMinima()
{ {
if( ! m_CurrentLM ) return; if (m_CurrentLM == m_MinimaList.end()) return;
m_CurrentLM = m_CurrentLM->Next; ++m_CurrentLM;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
IntRect ClipperBase::GetBounds() IntRect ClipperBase::GetBounds()
{ {
IntRect result; IntRect result;
LocalMinima* lm = m_MinimaList; MinimaList::iterator lm = m_MinimaList.begin();
if (!lm) if (lm == m_MinimaList.end())
{ {
result.left = result.top = result.right = result.bottom = 0; result.left = result.top = result.right = result.bottom = 0;
return result; return result;
...@@ -1416,10 +1308,9 @@ IntRect ClipperBase::GetBounds() ...@@ -1416,10 +1308,9 @@ IntRect ClipperBase::GetBounds()
result.top = lm->LeftBound->Bot.Y; result.top = lm->LeftBound->Bot.Y;
result.right = lm->LeftBound->Bot.X; result.right = lm->LeftBound->Bot.X;
result.bottom = lm->LeftBound->Bot.Y; result.bottom = lm->LeftBound->Bot.Y;
while (lm) while (lm != m_MinimaList.end())
{ {
if (lm->LeftBound->Bot.Y > result.bottom) result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y);
result.bottom = lm->LeftBound->Bot.Y;
TEdge* e = lm->LeftBound; TEdge* e = lm->LeftBound;
for (;;) { for (;;) {
TEdge* bottomE = e; TEdge* bottomE = e;
...@@ -1429,16 +1320,15 @@ IntRect ClipperBase::GetBounds() ...@@ -1429,16 +1320,15 @@ IntRect ClipperBase::GetBounds()
if (e->Bot.X > result.right) result.right = e->Bot.X; if (e->Bot.X > result.right) result.right = e->Bot.X;
e = e->NextInLML; e = e->NextInLML;
} }
if (e->Bot.X < result.left) result.left = e->Bot.X; result.left = std::min(result.left, e->Bot.X);
if (e->Bot.X > result.right) result.right = e->Bot.X; result.right = std::max(result.right, e->Bot.X);
if (e->Top.X < result.left) result.left = e->Top.X; result.left = std::min(result.left, e->Top.X);
if (e->Top.X > result.right) result.right = e->Top.X; result.right = std::max(result.right, e->Top.X);
if (e->Top.Y < result.top) result.top = e->Top.Y; result.top = std::min(result.top, e->Top.Y);
if (bottomE == lm->LeftBound) e = lm->RightBound; if (bottomE == lm->LeftBound) e = lm->RightBound;
else break; else break;
} }
lm = lm->Next; ++lm;
} }
return result; return result;
} }
...@@ -1466,12 +1356,11 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor ...@@ -1466,12 +1356,11 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor
Clipper::~Clipper() //destructor Clipper::~Clipper() //destructor
{ {
Clear(); Clear();
m_Scanbeam.clear();
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef use_xyz #ifdef use_xyz
void Clipper::ZFillFunction(TZFillCallback zFillFunc) void Clipper::ZFillFunction(ZFillCallback zFillFunc)
{ {
m_ZFill = zFillFunc; m_ZFill = zFillFunc;
} }
...@@ -1481,15 +1370,11 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc) ...@@ -1481,15 +1370,11 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc)
void Clipper::Reset() void Clipper::Reset()
{ {
ClipperBase::Reset(); ClipperBase::Reset();
m_Scanbeam.clear(); m_Scanbeam = ScanbeamList();
m_ActiveEdges = 0; m_ActiveEdges = 0;
m_SortedEdges = 0; m_SortedEdges = 0;
LocalMinima* lm = m_MinimaList; for (MinimaList::iterator lm = m_MinimaList.begin(); lm != m_MinimaList.end(); ++lm)
while (lm)
{
InsertScanbeam(lm->Y); InsertScanbeam(lm->Y);
lm = lm->Next;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1550,7 +1435,7 @@ bool Clipper::ExecuteInternal() ...@@ -1550,7 +1435,7 @@ bool Clipper::ExecuteInternal()
bool succeeded = true; bool succeeded = true;
try { try {
Reset(); Reset();
if (!m_CurrentLM) return false; if (m_CurrentLM == m_MinimaList.end()) return true;
cInt botY = PopScanbeam(); cInt botY = PopScanbeam();
do { do {
InsertLocalMinimaIntoAEL(botY); InsertLocalMinimaIntoAEL(botY);
...@@ -1558,11 +1443,11 @@ bool Clipper::ExecuteInternal() ...@@ -1558,11 +1443,11 @@ bool Clipper::ExecuteInternal()
ProcessHorizontals(false); ProcessHorizontals(false);
if (m_Scanbeam.empty()) break; if (m_Scanbeam.empty()) break;
cInt topY = PopScanbeam(); cInt topY = PopScanbeam();
succeeded = ProcessIntersections(botY, topY); succeeded = ProcessIntersections(topY);
if (!succeeded) break; if (!succeeded) break;
ProcessEdgesAtTopOfScanbeam(topY); ProcessEdgesAtTopOfScanbeam(topY);
botY = topY; botY = topY;
} while (!m_Scanbeam.empty() || m_CurrentLM); } while (!m_Scanbeam.empty() || m_CurrentLM != m_MinimaList.end());
} }
catch(...) catch(...)
{ {
...@@ -1601,14 +1486,16 @@ bool Clipper::ExecuteInternal() ...@@ -1601,14 +1486,16 @@ bool Clipper::ExecuteInternal()
void Clipper::InsertScanbeam(const cInt Y) void Clipper::InsertScanbeam(const cInt Y)
{ {
m_Scanbeam.insert(Y); //if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates.
m_Scanbeam.push(Y);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
cInt Clipper::PopScanbeam() cInt Clipper::PopScanbeam()
{ {
cInt Y = *m_Scanbeam.begin(); const cInt Y = m_Scanbeam.top();
m_Scanbeam.erase(m_Scanbeam.begin()); m_Scanbeam.pop();
while (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) { m_Scanbeam.pop(); } // Pop duplicates.
return Y; return Y;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -1967,7 +1854,7 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt) ...@@ -1967,7 +1854,7 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
{ {
while( m_CurrentLM && ( m_CurrentLM->Y == botY ) ) while (m_CurrentLM != m_MinimaList.end() && (m_CurrentLM->Y == botY))
{ {
TEdge* lb = m_CurrentLM->LeftBound; TEdge* lb = m_CurrentLM->LeftBound;
TEdge* rb = m_CurrentLM->RightBound; TEdge* rb = m_CurrentLM->RightBound;
...@@ -2018,7 +1905,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) ...@@ -2018,7 +1905,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
Join* jr = m_GhostJoins[i]; Join* jr = m_GhostJoins[i];
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert //if the horizontal Rb and a 'ghost' horizontal overlap, then convert
//the 'ghost' join to a real join ready for later ... //the 'ghost' join to a real join ready for later ...
if (HorzSegmentsOverlap(jr->OutPt1->Pt, jr->OffPt, rb->Bot, rb->Top)) if (HorzSegmentsOverlap(jr->OutPt1->Pt.X, jr->OffPt.X, rb->Bot.X, rb->Top.X))
AddJoin(jr->OutPt1, Op1, jr->OffPt); AddJoin(jr->OutPt1, Op1, jr->OffPt);
} }
} }
...@@ -2088,45 +1975,34 @@ void Clipper::DeleteFromSEL(TEdge *e) ...@@ -2088,45 +1975,34 @@ void Clipper::DeleteFromSEL(TEdge *e)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef use_xyz #ifdef use_xyz
void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2)
void Clipper::SetZ(IntPoint& pt, TEdge& e)
{ {
pt.Z = 0; if (pt.Z != 0 || !m_ZFill) return;
if (m_ZFill) else if (pt == e1.Bot) pt.Z = e1.Bot.Z;
{ else if (pt == e1.Top) pt.Z = e1.Top.Z;
//put the 'preferred' point as first parameter ... else if (pt == e2.Bot) pt.Z = e2.Bot.Z;
if (e.OutIdx < 0) else if (pt == e2.Top) pt.Z = e2.Top.Z;
(*m_ZFill)(e.Bot, e.Top, pt); //outside a path so presume entering else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt);
else
(*m_ZFill)(e.Top, e.Bot, pt); //inside a path so presume exiting
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#endif #endif
void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt)
const IntPoint &Pt, bool protect)
{ {
//e1 will be to the Left of e2 BELOW the intersection. Therefore e1 is before
//e2 in AEL except when e1 is being inserted at the intersection point ...
bool e1stops = !protect && !e1->NextInLML &&
e1->Top.X == Pt.X && e1->Top.Y == Pt.Y;
bool e2stops = !protect && !e2->NextInLML &&
e2->Top.X == Pt.X && e2->Top.Y == Pt.Y;
bool e1Contributing = ( e1->OutIdx >= 0 ); bool e1Contributing = ( e1->OutIdx >= 0 );
bool e2Contributing = ( e2->OutIdx >= 0 ); bool e2Contributing = ( e2->OutIdx >= 0 );
#ifdef use_xyz
SetZ(Pt, *e1, *e2);
#endif
#ifdef use_lines #ifdef use_lines
//if either edge is on an OPEN path ... //if either edge is on an OPEN path ...
if (e1->WindDelta == 0 || e2->WindDelta == 0) if (e1->WindDelta == 0 || e2->WindDelta == 0)
{ {
//ignore subject-subject open path intersections UNLESS they //ignore subject-subject open path intersections UNLESS they
//are both open paths, AND they are both 'contributing maximas' ... //are both open paths, AND they are both 'contributing maximas' ...
if (e1->WindDelta == 0 && e2->WindDelta == 0) if (e1->WindDelta == 0 && e2->WindDelta == 0) return;
{
if ((e1stops || e2stops) && e1Contributing && e2Contributing)
AddLocalMaxPoly(e1, e2, Pt);
}
//if intersecting a subj line with a subj poly ... //if intersecting a subj line with a subj poly ...
else if (e1->PolyTyp == e2->PolyTyp && else if (e1->PolyTyp == e2->PolyTyp &&
...@@ -2165,13 +2041,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, ...@@ -2165,13 +2041,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
if (e2Contributing) e2->OutIdx = Unassigned; if (e2Contributing) e2->OutIdx = Unassigned;
} }
} }
if (e1stops)
if (e1->OutIdx < 0) DeleteFromAEL(e1);
else throw clipperException("Error intersecting polylines");
if (e2stops)
if (e2->OutIdx < 0) DeleteFromAEL(e2);
else throw clipperException("Error intersecting polylines");
return; return;
} }
#endif #endif
...@@ -2236,10 +2105,11 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, ...@@ -2236,10 +2105,11 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
if ( e1Contributing && e2Contributing ) if ( e1Contributing && e2Contributing )
{ {
if ( e1stops || e2stops || if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) ||
(e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) ||
(e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) )
{
AddLocalMaxPoly(e1, e2, Pt); AddLocalMaxPoly(e1, e2, Pt);
}
else else
{ {
AddOutPt(e1, Pt); AddOutPt(e1, Pt);
...@@ -2266,8 +2136,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, ...@@ -2266,8 +2136,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
SwapPolyIndexes(*e1, *e2); SwapPolyIndexes(*e1, *e2);
} }
} }
else if ( (e1Wc == 0 || e1Wc == 1) && else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1))
(e2Wc == 0 || e2Wc == 1) && !e1stops && !e2stops )
{ {
//neither edge is currently contributing ... //neither edge is currently contributing ...
...@@ -2286,7 +2155,9 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, ...@@ -2286,7 +2155,9 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
} }
if (e1->PolyTyp != e2->PolyTyp) if (e1->PolyTyp != e2->PolyTyp)
{
AddLocalMinPoly(e1, e2, Pt); AddLocalMinPoly(e1, e2, Pt);
}
else if (e1Wc == 1 && e2Wc == 1) else if (e1Wc == 1 && e2Wc == 1)
switch( m_ClipType ) { switch( m_ClipType ) {
case ctIntersection: case ctIntersection:
...@@ -2308,17 +2179,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, ...@@ -2308,17 +2179,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
else else
SwapSides( *e1, *e2 ); SwapSides( *e1, *e2 );
} }
if( (e1stops != e2stops) &&
( (e1stops && (e1->OutIdx >= 0)) || (e2stops && (e2->OutIdx >= 0)) ) )
{
SwapSides( *e1, *e2 );
SwapPolyIndexes( *e1, *e2 );
}
//finally, delete any non-contributing maxima edges ...
if( e1stops ) DeleteFromAEL( e1 );
if( e2stops ) DeleteFromAEL( e2 );
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -2509,12 +2369,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) ...@@ -2509,12 +2369,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
newOp->Prev = newOp; newOp->Prev = newOp;
if (!outRec->IsOpen) if (!outRec->IsOpen)
SetHoleState(e, outRec); SetHoleState(e, outRec);
#ifdef use_xyz e->OutIdx = outRec->Idx;
if (pt == e->Bot) newOp->Pt = e->Bot;
else if (pt == e->Top) newOp->Pt = e->Top;
else SetZ(newOp->Pt, *e);
#endif
e->OutIdx = outRec->Idx; //nb: do this after SetZ !
return newOp; return newOp;
} else } else
{ {
...@@ -2533,11 +2388,6 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) ...@@ -2533,11 +2388,6 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
newOp->Prev->Next = newOp; newOp->Prev->Next = newOp;
op->Prev = newOp; op->Prev = newOp;
if (ToFront) outRec->Pts = newOp; if (ToFront) outRec->Pts = newOp;
#ifdef use_xyz
if (pt == e->Bot) newOp->Pt = e->Bot;
else if (pt == e->Top) newOp->Pt = e->Top;
else SetZ(newOp->Pt, *e);
#endif
return newOp; return newOp;
} }
} }
...@@ -2704,37 +2554,6 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) ...@@ -2704,37 +2554,6 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
void Clipper::PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam)
{
//get the last Op for this horizontal edge
//the point may be anywhere along the horizontal ...
OutPt* outPt = m_PolyOuts[horzEdge->OutIdx]->Pts;
if (horzEdge->Side != esLeft) outPt = outPt->Prev;
//First, match up overlapping horizontal edges (eg when one polygon's
//intermediate horz edge overlaps an intermediate horz edge of another, or
//when one polygon sits on top of another) ...
//for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
//{
// Join* j = m_GhostJoins[i];
// if (HorzSegmentsOverlap(j->OutPt1->Pt, j->OffPt, horzEdge->Bot, horzEdge->Top))
// AddJoin(j->OutPt1, outPt, j->OffPt);
//}
//Also, since horizontal edges at the top of one SB are often removed from
//the AEL before we process the horizontal edges at the bottom of the next,
//we need to create 'ghost' Join records of 'contrubuting' horizontals that
//we can compare with horizontals at the bottom of the next SB.
if (isTopOfScanbeam)
{
if (outPt->Pt == horzEdge->Top)
AddGhostJoin(outPt, horzEdge->Bot);
else
AddGhostJoin(outPt, horzEdge->Top);
}
}
//------------------------------------------------------------------------------
/******************************************************************************* /*******************************************************************************
* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * * Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or *
* Bottom of a scanbeam) are processed as if layered. The order in which HEs * * Bottom of a scanbeam) are processed as if layered. The order in which HEs *
...@@ -2774,28 +2593,42 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) ...@@ -2774,28 +2593,42 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
if ((dir == dLeftToRight && e->Curr.X <= horzRight) || if ((dir == dLeftToRight && e->Curr.X <= horzRight) ||
(dir == dRightToLeft && e->Curr.X >= horzLeft)) (dir == dRightToLeft && e->Curr.X >= horzLeft))
{ {
if (horzEdge->OutIdx >= 0 && horzEdge->WindDelta != 0)
PrepareHorzJoins(horzEdge, isTopOfScanbeam);
//so far we're still in range of the horizontal Edge but make sure //so far we're still in range of the horizontal Edge but make sure
//we're at the last of consec. horizontals when matching with eMaxPair //we're at the last of consec. horizontals when matching with eMaxPair
if(e == eMaxPair && IsLastHorz) if(e == eMaxPair && IsLastHorz)
{ {
if (dir == dLeftToRight)
IntersectEdges(horzEdge, e, e->Top); if (horzEdge->OutIdx >= 0)
else {
IntersectEdges(e, horzEdge, e->Top); OutPt* op1 = AddOutPt(horzEdge, horzEdge->Top);
if (eMaxPair->OutIdx >= 0) throw clipperException("ProcessHorizontal error"); TEdge* eNextHorz = m_SortedEdges;
while (eNextHorz)
{
if (eNextHorz->OutIdx >= 0 &&
HorzSegmentsOverlap(horzEdge->Bot.X,
horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X))
{
OutPt* op2 = AddOutPt(eNextHorz, eNextHorz->Bot);
AddJoin(op2, op1, eNextHorz->Top);
}
eNextHorz = eNextHorz->NextInSEL;
}
AddGhostJoin(op1, horzEdge->Bot);
AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top);
}
DeleteFromAEL(horzEdge);
DeleteFromAEL(eMaxPair);
return; return;
} }
else if(dir == dLeftToRight) else if(dir == dLeftToRight)
{ {
IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
IntersectEdges(horzEdge, e, Pt, true); IntersectEdges(horzEdge, e, Pt);
} }
else else
{ {
IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y);
IntersectEdges( e, horzEdge, Pt, true); IntersectEdges( e, horzEdge, Pt);
} }
SwapPositionsInAEL( horzEdge, e ); SwapPositionsInAEL( horzEdge, e );
} }
...@@ -2804,9 +2637,6 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) ...@@ -2804,9 +2637,6 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
e = eNext; e = eNext;
} //end while } //end while
if (horzEdge->OutIdx >= 0 && horzEdge->WindDelta != 0)
PrepareHorzJoins(horzEdge, isTopOfScanbeam);
if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML)) if (horzEdge->NextInLML && IsHorizontal(*horzEdge->NextInLML))
{ {
UpdateEdgeIntoAEL(horzEdge); UpdateEdgeIntoAEL(horzEdge);
...@@ -2821,6 +2651,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) ...@@ -2821,6 +2651,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
if(horzEdge->OutIdx >= 0) if(horzEdge->OutIdx >= 0)
{ {
OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top); OutPt* op1 = AddOutPt( horzEdge, horzEdge->Top);
if (isTopOfScanbeam) AddGhostJoin(op1, horzEdge->Bot);
UpdateEdgeIntoAEL(horzEdge); UpdateEdgeIntoAEL(horzEdge);
if (horzEdge->WindDelta == 0) return; if (horzEdge->WindDelta == 0) return;
//nb: HorzEdge is no longer horizontal here //nb: HorzEdge is no longer horizontal here
...@@ -2846,22 +2677,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam) ...@@ -2846,22 +2677,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
else else
UpdateEdgeIntoAEL(horzEdge); UpdateEdgeIntoAEL(horzEdge);
} }
else if (eMaxPair)
{
if (eMaxPair->OutIdx >= 0)
{
if (dir == dLeftToRight)
IntersectEdges(horzEdge, eMaxPair, horzEdge->Top);
else else
IntersectEdges(eMaxPair, horzEdge, horzEdge->Top);
if (eMaxPair->OutIdx >= 0)
throw clipperException("ProcessHorizontal error");
} else
{
DeleteFromAEL(horzEdge);
DeleteFromAEL(eMaxPair);
}
} else
{ {
if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top);
DeleteFromAEL(horzEdge); DeleteFromAEL(horzEdge);
...@@ -2892,11 +2708,11 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e) ...@@ -2892,11 +2708,11 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
bool Clipper::ProcessIntersections(const cInt botY, const cInt topY) bool Clipper::ProcessIntersections(const cInt topY)
{ {
if( !m_ActiveEdges ) return true; if( !m_ActiveEdges ) return true;
try { try {
BuildIntersectList(botY, topY); BuildIntersectList(topY);
size_t IlSize = m_IntersectList.size(); size_t IlSize = m_IntersectList.size();
if (IlSize == 0) return true; if (IlSize == 0) return true;
if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList(); if (IlSize == 1 || FixupIntersectionOrder()) ProcessIntersectList();
...@@ -2921,7 +2737,7 @@ void Clipper::DisposeIntersectNodes() ...@@ -2921,7 +2737,7 @@ void Clipper::DisposeIntersectNodes()
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Clipper::BuildIntersectList(const cInt botY, const cInt topY) void Clipper::BuildIntersectList(const cInt topY)
{ {
if ( !m_ActiveEdges ) return; if ( !m_ActiveEdges ) return;
...@@ -2948,16 +2764,7 @@ void Clipper::BuildIntersectList(const cInt botY, const cInt topY) ...@@ -2948,16 +2764,7 @@ void Clipper::BuildIntersectList(const cInt botY, const cInt topY)
IntPoint Pt; IntPoint Pt;
if(e->Curr.X > eNext->Curr.X) if(e->Curr.X > eNext->Curr.X)
{ {
if (!IntersectPoint(*e, *eNext, Pt, m_UseFullRange) && e->Curr.X > eNext->Curr.X +1) IntersectPoint(*e, *eNext, Pt);
throw clipperException("Intersection error");
if (Pt.Y > botY)
{
Pt.Y = botY;
if (std::fabs(e->Dx) > std::fabs(eNext->Dx))
Pt.X = TopX(*eNext, botY); else
Pt.X = TopX(*e, botY);
}
IntersectNode * newNode = new IntersectNode; IntersectNode * newNode = new IntersectNode;
newNode->Edge1 = e; newNode->Edge1 = e;
newNode->Edge2 = eNext; newNode->Edge2 = eNext;
...@@ -2985,7 +2792,7 @@ void Clipper::ProcessIntersectList() ...@@ -2985,7 +2792,7 @@ void Clipper::ProcessIntersectList()
{ {
IntersectNode* iNode = m_IntersectList[i]; IntersectNode* iNode = m_IntersectList[i];
{ {
IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt, true); IntersectEdges( iNode->Edge1, iNode->Edge2, iNode->Pt);
SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 ); SwapPositionsInAEL( iNode->Edge1 , iNode->Edge2 );
} }
delete iNode; delete iNode;
...@@ -3044,7 +2851,7 @@ void Clipper::DoMaxima(TEdge *e) ...@@ -3044,7 +2851,7 @@ void Clipper::DoMaxima(TEdge *e)
TEdge* eNext = e->NextInAEL; TEdge* eNext = e->NextInAEL;
while(eNext && eNext != eMaxPair) while(eNext && eNext != eMaxPair)
{ {
IntersectEdges(e, eNext, e->Top, true); IntersectEdges(e, eNext, e->Top);
SwapPositionsInAEL(e, eNext); SwapPositionsInAEL(e, eNext);
eNext = e->NextInAEL; eNext = e->NextInAEL;
} }
...@@ -3056,7 +2863,9 @@ void Clipper::DoMaxima(TEdge *e) ...@@ -3056,7 +2863,9 @@ void Clipper::DoMaxima(TEdge *e)
} }
else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 )
{ {
IntersectEdges( e, eMaxPair, e->Top); if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top);
DeleteFromAEL(e);
DeleteFromAEL(eMaxPair);
} }
#ifdef use_lines #ifdef use_lines
else if (e->WindDelta == 0) else if (e->WindDelta == 0)
...@@ -3124,9 +2933,13 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) ...@@ -3124,9 +2933,13 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) &&
(ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0))
{ {
OutPt* op = AddOutPt(ePrev, e->Curr); IntPoint pt = e->Curr;
OutPt* op2 = AddOutPt(e, e->Curr); #ifdef use_xyz
AddJoin(op, op2, e->Curr); //StrictlySimple (type-3) join SetZ(pt, *ePrev, *e);
#endif
OutPt* op = AddOutPt(ePrev, pt);
OutPt* op2 = AddOutPt(e, pt);
AddJoin(op, op2, pt); //StrictlySimple (type-3) join
} }
} }
...@@ -3508,6 +3321,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) ...@@ -3508,6 +3321,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
(j->OffPt == j->OutPt2->Pt)) (j->OffPt == j->OutPt2->Pt))
{ {
//Strictly Simple join ... //Strictly Simple join ...
if (outRec1 != outRec2) return false;
op1b = j->OutPt1->Next; op1b = j->OutPt1->Next;
while (op1b != op1 && (op1b->Pt == j->OffPt)) while (op1b != op1 && (op1b->Pt == j->OffPt))
op1b = op1b->Next; op1b = op1b->Next;
...@@ -3648,13 +3462,23 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) ...@@ -3648,13 +3462,23 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) static OutRec* ParseFirstLeft(OutRec* FirstLeft)
{ {
while (FirstLeft && !FirstLeft->Pts)
FirstLeft = FirstLeft->FirstLeft;
return FirstLeft;
}
//------------------------------------------------------------------------------
void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
{
//tests if NewOutRec contains the polygon before reassigning FirstLeft
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
{ {
OutRec* outRec = m_PolyOuts[i]; OutRec* outRec = m_PolyOuts[i];
if (outRec->Pts && outRec->FirstLeft == OldOutRec) if (!outRec->Pts || !outRec->FirstLeft) continue;
OutRec* firstLeft = ParseFirstLeft(outRec->FirstLeft);
if (firstLeft == OldOutRec)
{ {
if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) if (Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts))
outRec->FirstLeft = NewOutRec; outRec->FirstLeft = NewOutRec;
...@@ -3665,6 +3489,7 @@ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) ...@@ -3665,6 +3489,7 @@ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
{ {
//reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon
for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i) for (PolyOutList::size_type i = 0; i < m_PolyOuts.size(); ++i)
{ {
OutRec* outRec = m_PolyOuts[i]; OutRec* outRec = m_PolyOuts[i];
...@@ -3673,14 +3498,6 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) ...@@ -3673,14 +3498,6 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
static OutRec* ParseFirstLeft(OutRec* FirstLeft)
{
while (FirstLeft && !FirstLeft->Pts)
FirstLeft = FirstLeft->FirstLeft;
return FirstLeft;
}
//------------------------------------------------------------------------------
void Clipper::JoinCommonEdges() void Clipper::JoinCommonEdges()
{ {
for (JoinList::size_type i = 0; i < m_Joins.size(); i++) for (JoinList::size_type i = 0; i < m_Joins.size(); i++)
...@@ -3848,8 +3665,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType ...@@ -3848,8 +3665,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
(path[i].Y == newNode->Contour[k].Y && (path[i].Y == newNode->Contour[k].Y &&
path[i].X < newNode->Contour[k].X)) k = j; path[i].X < newNode->Contour[k].X)) k = j;
} }
if ((endType == etClosedPolygon && j < 2) || if (endType == etClosedPolygon && j < 2)
(endType != etClosedPolygon && j < 0))
{ {
delete newNode; delete newNode;
return; return;
...@@ -3859,7 +3675,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType ...@@ -3859,7 +3675,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
//if this path's lowest pt is lower than all the others then update m_lowest //if this path's lowest pt is lower than all the others then update m_lowest
if (endType != etClosedPolygon) return; if (endType != etClosedPolygon) return;
if (m_lowest.X < 0) if (m_lowest.X < 0)
m_lowest = IntPoint(0, k); m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k);
else else
{ {
IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y];
...@@ -3965,6 +3781,7 @@ void ClipperOffset::Execute(PolyTree& solution, double delta) ...@@ -3965,6 +3781,7 @@ void ClipperOffset::Execute(PolyTree& solution, double delta)
PolyNode* outerNode = solution.Childs[0]; PolyNode* outerNode = solution.Childs[0];
solution.Childs.reserve(outerNode->ChildCount()); solution.Childs.reserve(outerNode->ChildCount());
solution.Childs[0] = outerNode->Childs[0]; solution.Childs[0] = outerNode->Childs[0];
solution.Childs[0]->Parent = outerNode->Parent;
for (int i = 1; i < outerNode->ChildCount(); ++i) for (int i = 1; i < outerNode->ChildCount(); ++i)
solution.AddChild(*outerNode->Childs[i]); solution.AddChild(*outerNode->Childs[i]);
} }
...@@ -4149,8 +3966,20 @@ void ClipperOffset::DoOffset(double delta) ...@@ -4149,8 +3966,20 @@ void ClipperOffset::DoOffset(double delta)
void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
{ {
//cross product ...
m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y);
if (m_sinA < 0.00005 && m_sinA > -0.00005) return; if (std::fabs(m_sinA * m_delta) < 1.0)
{
//dot product ...
double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y );
if (cosA > 0) // angle => 0 degrees
{
m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta),
Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta)));
return;
}
//else angle => 180 degrees
}
else if (m_sinA > 1.0) m_sinA = 1.0; else if (m_sinA > 1.0) m_sinA = 1.0;
else if (m_sinA < -1.0) m_sinA = -1.0; else if (m_sinA < -1.0) m_sinA = -1.0;
...@@ -4204,7 +4033,7 @@ void ClipperOffset::DoRound(int j, int k) ...@@ -4204,7 +4033,7 @@ void ClipperOffset::DoRound(int j, int k)
{ {
double a = std::atan2(m_sinA, double a = std::atan2(m_sinA,
m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y);
int steps = (int)Round(m_StepsPerRad * std::fabs(a)); int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1);
double X = m_normals[k].X, Y = m_normals[k].Y, X2; double X = m_normals[k].X, Y = m_normals[k].Y, X2;
for (int i = 0; i < steps; ++i) for (int i = 0; i < steps; ++i)
...@@ -4232,7 +4061,7 @@ void Clipper::DoSimplePolygons() ...@@ -4232,7 +4061,7 @@ void Clipper::DoSimplePolygons()
{ {
OutRec* outrec = m_PolyOuts[i++]; OutRec* outrec = m_PolyOuts[i++];
OutPt* op = outrec->Pts; OutPt* op = outrec->Pts;
if (!op) continue; if (!op || outrec->IsOpen) continue;
do //for each Pt in Polygon until duplicate found do ... do //for each Pt in Polygon until duplicate found do ...
{ {
OutPt* op2 = op->Next; OutPt* op2 = op->Next;
...@@ -4257,6 +4086,7 @@ void Clipper::DoSimplePolygons() ...@@ -4257,6 +4086,7 @@ void Clipper::DoSimplePolygons()
//OutRec2 is contained by OutRec1 ... //OutRec2 is contained by OutRec1 ...
outrec2->IsHole = !outrec->IsHole; outrec2->IsHole = !outrec->IsHole;
outrec2->FirstLeft = outrec; outrec2->FirstLeft = outrec;
if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec);
} }
else else
if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts))
...@@ -4266,11 +4096,14 @@ void Clipper::DoSimplePolygons() ...@@ -4266,11 +4096,14 @@ void Clipper::DoSimplePolygons()
outrec->IsHole = !outrec2->IsHole; outrec->IsHole = !outrec2->IsHole;
outrec2->FirstLeft = outrec->FirstLeft; outrec2->FirstLeft = outrec->FirstLeft;
outrec->FirstLeft = outrec2; outrec->FirstLeft = outrec2;
} else if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2);
}
else
{ {
//the 2 polygons are separate ... //the 2 polygons are separate ...
outrec2->IsHole = outrec->IsHole; outrec2->IsHole = outrec->IsHole;
outrec2->FirstLeft = outrec->FirstLeft; outrec2->FirstLeft = outrec->FirstLeft;
if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2);
} }
op2 = op; //ie get ready for the Next iteration op2 = op; //ie get ready for the Next iteration
} }
...@@ -4348,7 +4181,27 @@ double DistanceFromLineSqrd( ...@@ -4348,7 +4181,27 @@ double DistanceFromLineSqrd(
bool SlopesNearCollinear(const IntPoint& pt1, bool SlopesNearCollinear(const IntPoint& pt1,
const IntPoint& pt2, const IntPoint& pt3, double distSqrd) const IntPoint& pt2, const IntPoint& pt3, double distSqrd)
{ {
//this function is more accurate when the point that's geometrically
//between the other 2 points is the one that's tested for distance.
//ie makes it more likely to pick up 'spikes' ...
if (Abs(pt1.X - pt2.X) > Abs(pt1.Y - pt2.Y))
{
if ((pt1.X > pt2.X) == (pt1.X < pt3.X))
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
else if ((pt2.X > pt1.X) == (pt2.X < pt3.X))
return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
else
return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
}
else
{
if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y))
return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd;
else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y))
return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd;
else
return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -4476,8 +4329,8 @@ void Minkowski(const Path& poly, const Path& path, ...@@ -4476,8 +4329,8 @@ void Minkowski(const Path& poly, const Path& path,
pp.push_back(p); pp.push_back(p);
} }
Paths quads; solution.clear();
quads.reserve((pathCnt + delta) * (polyCnt + 1)); solution.reserve((pathCnt + delta) * (polyCnt + 1));
for (size_t i = 0; i < pathCnt - 1 + delta; ++i) for (size_t i = 0; i < pathCnt - 1 + delta; ++i)
for (size_t j = 0; j < polyCnt; ++j) for (size_t j = 0; j < polyCnt; ++j)
{ {
...@@ -4488,23 +4341,30 @@ void Minkowski(const Path& poly, const Path& path, ...@@ -4488,23 +4341,30 @@ void Minkowski(const Path& poly, const Path& path,
quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]);
quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]);
if (!Orientation(quad)) ReversePath(quad); if (!Orientation(quad)) ReversePath(quad);
quads.push_back(quad); solution.push_back(quad);
} }
}
//------------------------------------------------------------------------------
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed)
{
Minkowski(pattern, path, solution, true, pathIsClosed);
Clipper c; Clipper c;
c.AddPaths(quads, ptSubject, true); c.AddPaths(solution, ptSubject, true);
c.Execute(ctUnion, solution, pftNonZero, pftNonZero); c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) void TranslatePath(const Path& input, Path& output, IntPoint delta)
{ {
Minkowski(pattern, path, solution, true, pathIsClosed); //precondition: input != output
output.resize(input.size());
for (size_t i = 0; i < input.size(); ++i)
output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed)
PolyFillType pathFillType, bool pathIsClosed)
{ {
Clipper c; Clipper c;
for (size_t i = 0; i < paths.size(); ++i) for (size_t i = 0; i < paths.size(); ++i)
...@@ -4512,21 +4372,29 @@ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, ...@@ -4512,21 +4372,29 @@ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution,
Paths tmp; Paths tmp;
Minkowski(pattern, paths[i], tmp, true, pathIsClosed); Minkowski(pattern, paths[i], tmp, true, pathIsClosed);
c.AddPaths(tmp, ptSubject, true); c.AddPaths(tmp, ptSubject, true);
if (pathIsClosed)
{
Path tmp2;
TranslatePath(paths[i], tmp2, pattern[0]);
c.AddPath(tmp2, ptClip, true);
} }
if (pathIsClosed) c.AddPaths(paths, ptClip, true); }
c.Execute(ctUnion, solution, pathFillType, pathFillType); c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution)
{ {
Minkowski(poly1, poly2, solution, false, true); Minkowski(poly1, poly2, solution, false, true);
Clipper c;
c.AddPaths(solution, ptSubject, true);
c.Execute(ctUnion, solution, pftNonZero, pftNonZero);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
enum NodeType {ntAny, ntOpen, ntClosed}; enum NodeType {ntAny, ntOpen, ntClosed};
void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& paths) void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths)
{ {
bool match = true; bool match = true;
if (nodetype == ntClosed) match = !polynode.IsOpen(); if (nodetype == ntClosed) match = !polynode.IsOpen();
...@@ -4535,7 +4403,7 @@ void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& p ...@@ -4535,7 +4403,7 @@ void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& p
if (!polynode.Contour.empty() && match) if (!polynode.Contour.empty() && match)
paths.push_back(polynode.Contour); paths.push_back(polynode.Contour);
for (int i = 0; i < polynode.ChildCount(); ++i) for (int i = 0; i < polynode.ChildCount(); ++i)
AddPolyNodeToPolygons(*polynode.Childs[i], nodetype, paths); AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -4543,7 +4411,7 @@ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) ...@@ -4543,7 +4411,7 @@ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
{ {
paths.resize(0); paths.resize(0);
paths.reserve(polytree.Total()); paths.reserve(polytree.Total());
AddPolyNodeToPolygons(polytree, ntAny, paths); AddPolyNodeToPaths(polytree, ntAny, paths);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -4551,7 +4419,7 @@ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) ...@@ -4551,7 +4419,7 @@ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
{ {
paths.resize(0); paths.resize(0);
paths.reserve(polytree.Total()); paths.reserve(polytree.Total());
AddPolyNodeToPolygons(polytree, ntClosed, paths); AddPolyNodeToPaths(polytree, ntClosed, paths);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -4593,18 +4461,4 @@ std::ostream& operator <<(std::ostream &s, const Paths &p) ...@@ -4593,18 +4461,4 @@ std::ostream& operator <<(std::ostream &s, const Paths &p)
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef use_deprecated
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType_ endtype, double limit)
{
ClipperOffset co(limit, limit);
co.AddPaths(in_polys, jointype, (EndType)endtype);
co.Execute(out_polys, delta);
}
//------------------------------------------------------------------------------
#endif
} //ClipperLib namespace } //ClipperLib namespace
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 6.1.3a * * Version : 6.2.1 *
* Date : 22 January 2014 * * Date : 31 October 2014 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2014 * * Copyright : Angus Johnson 2010-2014 *
* * * *
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
#ifndef clipper_hpp #ifndef clipper_hpp
#define clipper_hpp #define clipper_hpp
#define CLIPPER_VERSION "6.1.3" #define CLIPPER_VERSION "6.2.0"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This //use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340 //improve performance but coordinate values are limited to the range +/- 46340
...@@ -46,9 +46,8 @@ ...@@ -46,9 +46,8 @@
//use_lines: Enables line clipping. Adds a very minor cost to performance. //use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines //#define use_lines
//use_deprecated: Enables support for the obsolete OffsetPaths() function //use_deprecated: Enables temporary support for the obsolete functions
//which has been replace with the ClipperOffset class. //#define use_deprecated
#define use_deprecated
#include <vector> #include <vector>
#include <set> #include <set>
...@@ -57,6 +56,7 @@ ...@@ -57,6 +56,7 @@
#include <cstdlib> #include <cstdlib>
#include <ostream> #include <ostream>
#include <functional> #include <functional>
#include <queue>
namespace ClipperLib { namespace ClipperLib {
...@@ -69,11 +69,16 @@ enum PolyType { ptSubject, ptClip }; ...@@ -69,11 +69,16 @@ enum PolyType { ptSubject, ptClip };
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
#ifdef use_int32 #ifdef use_int32
typedef int cInt; typedef int cInt;
typedef unsigned int cUInt; static cInt const loRange = 0x7FFF;
static cInt const hiRange = 0x7FFF;
#else #else
typedef signed long long cInt; typedef signed long long cInt;
typedef unsigned long long cUInt; static cInt const loRange = 0x3FFFFFFF;
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
typedef signed long long long64; //used by Int128 class
typedef unsigned long long ulong64;
#endif #endif
struct IntPoint { struct IntPoint {
...@@ -117,15 +122,12 @@ struct DoublePoint ...@@ -117,15 +122,12 @@ struct DoublePoint
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#ifdef use_xyz #ifdef use_xyz
typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt); typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
#endif #endif
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter}; enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
#ifdef use_deprecated
enum EndType_ {etClosed, etButt = 2, etSquare, etRound};
#endif
class PolyNode; class PolyNode;
typedef std::vector< PolyNode* > PolyNodes; typedef std::vector< PolyNode* > PolyNodes;
...@@ -134,6 +136,7 @@ class PolyNode ...@@ -134,6 +136,7 @@ class PolyNode
{ {
public: public:
PolyNode(); PolyNode();
virtual ~PolyNode(){};
Path Contour; Path Contour;
PolyNodes Childs; PolyNodes Childs;
PolyNode* Parent; PolyNode* Parent;
...@@ -168,11 +171,6 @@ bool Orientation(const Path &poly); ...@@ -168,11 +171,6 @@ bool Orientation(const Path &poly);
double Area(const Path &poly); double Area(const Path &poly);
int PointInPolygon(const IntPoint &pt, const Path &path); int PointInPolygon(const IntPoint &pt, const Path &path);
#ifdef use_deprecated
void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType_ endtype, double limit = 0);
#endif
void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
...@@ -183,8 +181,7 @@ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1. ...@@ -183,8 +181,7 @@ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.
void CleanPolygons(Paths& polys, double distance = 1.415); void CleanPolygons(Paths& polys, double distance = 1.415);
void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
void MinkowskiSum(const Path& pattern, const Paths& paths, void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
Paths& solution, PolyFillType pathFillType, bool pathIsClosed);
void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
...@@ -202,7 +199,7 @@ enum EdgeSide { esLeft = 1, esRight = 2}; ...@@ -202,7 +199,7 @@ enum EdgeSide { esLeft = 1, esRight = 2};
//forward declarations (for stuff used internally) ... //forward declarations (for stuff used internally) ...
struct TEdge; struct TEdge;
struct IntersectNode; struct IntersectNode;
struct LocalMinima; struct LocalMinimum;
struct Scanbeam; struct Scanbeam;
struct OutPt; struct OutPt;
struct OutRec; struct OutRec;
...@@ -213,7 +210,6 @@ typedef std::vector < TEdge* > EdgeList; ...@@ -213,7 +210,6 @@ typedef std::vector < TEdge* > EdgeList;
typedef std::vector < Join* > JoinList; typedef std::vector < Join* > JoinList;
typedef std::vector < IntersectNode* > IntersectList; typedef std::vector < IntersectNode* > IntersectList;
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be //ClipperBase is the ancestor to the Clipper class. It should not be
...@@ -236,12 +232,14 @@ protected: ...@@ -236,12 +232,14 @@ protected:
void PopLocalMinima(); void PopLocalMinima();
virtual void Reset(); virtual void Reset();
TEdge* ProcessBound(TEdge* E, bool IsClockwise); TEdge* ProcessBound(TEdge* E, bool IsClockwise);
void InsertLocalMinima(LocalMinima *newLm);
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed); void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
TEdge* DescendToMin(TEdge *&E); TEdge* DescendToMin(TEdge *&E);
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
LocalMinima *m_CurrentLM;
LocalMinima *m_MinimaList; typedef std::vector<LocalMinimum> MinimaList;
MinimaList::iterator m_CurrentLM;
MinimaList m_MinimaList;
bool m_UseFullRange; bool m_UseFullRange;
EdgeList m_edges; EdgeList m_edges;
bool m_PreserveCollinear; bool m_PreserveCollinear;
...@@ -268,7 +266,7 @@ public: ...@@ -268,7 +266,7 @@ public:
void StrictlySimple(bool value) {m_StrictSimple = value;}; void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0) //set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz #ifdef use_xyz
void ZFillFunction(TZFillCallback zFillFunc); void ZFillFunction(ZFillCallback zFillFunc);
#endif #endif
protected: protected:
void Reset(); void Reset();
...@@ -279,7 +277,8 @@ private: ...@@ -279,7 +277,8 @@ private:
JoinList m_GhostJoins; JoinList m_GhostJoins;
IntersectList m_IntersectList; IntersectList m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
std::set< cInt, std::greater<cInt> > m_Scanbeam; typedef std::priority_queue<cInt> ScanbeamList;
ScanbeamList m_Scanbeam;
TEdge *m_ActiveEdges; TEdge *m_ActiveEdges;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
bool m_ExecuteLocked; bool m_ExecuteLocked;
...@@ -289,7 +288,7 @@ private: ...@@ -289,7 +288,7 @@ private:
bool m_UsingPolyTree; bool m_UsingPolyTree;
bool m_StrictSimple; bool m_StrictSimple;
#ifdef use_xyz #ifdef use_xyz
TZFillCallback m_ZFill; //custom callback ZFillCallback m_ZFill; //custom callback
#endif #endif
void SetWindingCount(TEdge& edge); void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddFillType(const TEdge& edge) const;
...@@ -308,21 +307,19 @@ private: ...@@ -308,21 +307,19 @@ private:
bool IsTopHorz(const cInt XPos); bool IsTopHorz(const cInt XPos);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DoMaxima(TEdge *e); void DoMaxima(TEdge *e);
void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
void ProcessHorizontals(bool IsTopOfScanbeam); void ProcessHorizontals(bool IsTopOfScanbeam);
void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam); void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
OutRec* GetOutRec(int idx); OutRec* GetOutRec(int idx);
void AppendPolygon(TEdge *e1, TEdge *e2); void AppendPolygon(TEdge *e1, TEdge *e2);
void IntersectEdges(TEdge *e1, TEdge *e2, void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
const IntPoint &pt, bool protect = false);
OutRec* CreateOutRec(); OutRec* CreateOutRec();
OutPt* AddOutPt(TEdge *e, const IntPoint &pt); OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllOutRecs(); void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index); void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const cInt botY, const cInt topY); bool ProcessIntersections(const cInt topY);
void BuildIntersectList(const cInt botY, const cInt topY); void BuildIntersectList(const cInt topY);
void ProcessIntersectList(); void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const cInt topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Paths& polys); void BuildResult(Paths& polys);
...@@ -344,7 +341,7 @@ private: ...@@ -344,7 +341,7 @@ private:
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef use_xyz #ifdef use_xyz
void SetZ(IntPoint& pt, TEdge& e); void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
#endif #endif
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment