diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm
index 374544dfe..8bc57f53d 100644
--- a/lib/Slic3r/GUI/3DScene.pm
+++ b/lib/Slic3r/GUI/3DScene.pm
@@ -377,7 +377,9 @@ sub mouse_event {
         $self->_layer_height_edited(undef);
     } elsif ($e->Moving) {
         $self->_mouse_pos($pos);
-        $self->Refresh;
+        # Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor
+        # hovers over.
+        $self->Refresh if ($self->enable_picking);
     } else {
         $e->Skip();
     }
@@ -1047,9 +1049,10 @@ sub Render {
 
     $self->draw_active_object_annotations;
     
-    glFlush();
- 
     $self->SwapBuffers();
+
+    # Calling glFinish has a performance penalty, but it seems to fix some OpenGL driver hang-up with extremely large scenes.
+    glFinish();
 }
 
 sub draw_volumes {
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 720294cd0..c0d80629c 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -260,44 +260,35 @@ sub generate_support_material {
     
     $self->clear_support_layers;
     
-    if ((!$self->config->support_material && $self->config->raft_layers == 0) || scalar(@{$self->layers}) < 2) {
-        $self->set_step_done(STEP_SUPPORTMATERIAL);
-        return;
+    if (($self->config->support_material || $self->config->raft_layers > 0) && scalar(@{$self->layers}) > 1) {
+        $self->print->status_cb->(85, "Generating support material");    
+        if (0) {
+            # Old supports, Perl implementation.
+            my $first_layer_flow = Slic3r::Flow->new_from_width(
+                width               => ($self->print->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
+                role                => FLOW_ROLE_SUPPORT_MATERIAL,
+                nozzle_diameter     => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
+                                        // $self->print->config->nozzle_diameter->[0],
+                layer_height        => $self->config->get_abs_value('first_layer_height'),
+                bridge_flow_ratio   => 0,
+            );            
+            my $support_material = Slic3r::Print::SupportMaterial->new(
+                print_config        => $self->print->config,
+                object_config       => $self->config,
+                first_layer_flow    => $first_layer_flow,
+                flow                => $self->support_material_flow,
+                interface_flow      => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
+            );
+            $support_material->generate($self);
+        } else {
+            # New supports, C++ implementation.
+            $self->_generate_support_material;
+        }
     }
-    $self->print->status_cb->(85, "Generating support material");
-    
-    $self->_support_material->generate($self);
     
     $self->set_step_done(STEP_SUPPORTMATERIAL);
 }
 
-sub _support_material {
-    my ($self) = @_;
-    
-    my $first_layer_flow = Slic3r::Flow->new_from_width(
-        width               => ($self->print->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
-        role                => FLOW_ROLE_SUPPORT_MATERIAL,
-        nozzle_diameter     => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
-                                // $self->print->config->nozzle_diameter->[0],
-        layer_height        => $self->config->get_abs_value('first_layer_height'),
-        bridge_flow_ratio   => 0,
-    );
-    
-    if (1) {
-        # Old supports, Perl implementation.
-        return Slic3r::Print::SupportMaterial->new(
-            print_config        => $self->print->config,
-            object_config       => $self->config,
-            first_layer_flow    => $first_layer_flow,
-            flow                => $self->support_material_flow,
-            interface_flow      => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
-        );
-    } else {
-        # New supports, C++ implementation.
-        return Slic3r::Print::SupportMaterial2->new($self);
-    }
-}
-
 # Idempotence of this method is guaranteed by the fact that we don't remove things from
 # fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
 sub clip_fill_surfaces {
diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm
index b4caffc7d..8b77e8808 100644
--- a/lib/Slic3r/Print/SupportMaterial.pm
+++ b/lib/Slic3r/Print/SupportMaterial.pm
@@ -20,6 +20,7 @@ has 'interface_flow'    => (is => 'rw', required => 1);
 use constant DEBUG_CONTACT_ONLY => 0;
 
 # increment used to reach MARGIN in steps to avoid trespassing thin objects
+use constant MARGIN => 1.5;
 use constant MARGIN_STEP => MARGIN/3;
 
 # generate a tree-like structure to save material
diff --git a/xs/MANIFEST b/xs/MANIFEST
index 8ea48192b..01b9e1cd3 100644
--- a/xs/MANIFEST
+++ b/xs/MANIFEST
@@ -209,7 +209,6 @@ xsp/Polygon.xsp
 xsp/Polyline.xsp
 xsp/PolylineCollection.xsp
 xsp/Print.xsp
-xsp/SupportMaterial.xsp
 xsp/Surface.xsp
 xsp/SurfaceCollection.xsp
 xsp/TriangleMesh.xsp
diff --git a/xs/src/libslic3r/EdgeGrid.cpp b/xs/src/libslic3r/EdgeGrid.cpp
index 4d1432722..b39b12ab8 100644
--- a/xs/src/libslic3r/EdgeGrid.cpp
+++ b/xs/src/libslic3r/EdgeGrid.cpp
@@ -1222,17 +1222,39 @@ bool EdgeGrid::Grid::signed_distance(const Point &pt, coord_t search_radius, coo
 	return true;
 }
 
-Polygons EdgeGrid::Grid::contours_simplified() const
+Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const
 {
 	typedef std::unordered_multimap<Point, int, PointHash> EndPointMapType;
+	// 0) Prepare a binary grid.
+	size_t cell_rows = m_rows + 2;
+	size_t cell_cols = m_cols + 2;
+	std::vector<char> cell_inside(cell_rows * cell_cols, false);
+	for (int r = 0; r < int(cell_rows); ++ r)
+		for (int c = 0; c < int(cell_cols); ++ c)
+			cell_inside[r * cell_cols + c] = cell_inside_or_crossing(r - 1, c - 1);
+	// Fill in empty cells, which have a left / right neighbor filled.
+	// Fill in empty cells, which have the top / bottom neighbor filled.
+	{
+		std::vector<char> cell_inside2(cell_inside);
+		for (int r = 1; r + 1 < int(cell_rows); ++ r) {
+			for (int c = 1; c + 1 < int(cell_cols); ++ c) {
+				int addr = r * cell_cols + c;
+				if ((cell_inside2[addr - 1] && cell_inside2[addr + 1]) ||
+					(cell_inside2[addr - cell_cols] && cell_inside2[addr + cell_cols]))
+					cell_inside[addr] = true;
+			}
+		}
+	}
+
 	// 1) Collect the lines.
 	std::vector<Line> lines;
 	EndPointMapType start_point_to_line_idx;
 	for (int r = 0; r <= int(m_rows); ++ r) {
 		for (int c = 0; c <= int(m_cols); ++ c) {
-			bool left    = cell_inside_or_crossing(r  , c-1);
-			bool top     = cell_inside_or_crossing(r-1, c  );
-			bool current = cell_inside_or_crossing(r  , c  );
+			int  addr    = (r + 1) * cell_cols + c + 1;
+			bool left    = cell_inside[addr - 1];
+			bool top     = cell_inside[addr - cell_cols];
+			bool current = cell_inside[addr];
 			if (left != current) {
 				lines.push_back(
 					left ? 
@@ -1312,7 +1334,6 @@ Polygons EdgeGrid::Grid::contours_simplified() const
 		// Remove collineaer points.
 		Points pts;
 		pts.reserve(poly.points.size());
-		coord_t downscale = 5;
 		for (size_t j = 0; j < poly.points.size(); ++ j) {
 			size_t j0 = (j == 0) ? poly.points.size() - 1 : j - 1;
 			size_t j2 = (j + 1 == poly.points.size()) ? 0 : j + 1;
@@ -1320,8 +1341,8 @@ Polygons EdgeGrid::Grid::contours_simplified() const
 			if (v.x != 0 && v.y != 0) {
 				// This is a corner point. Copy it to the output contour.
 				Point p = poly.points[j];
-				p.y += (v.x < 0) ? downscale : -downscale;
-				p.x += (v.y > 0) ? downscale : -downscale;
+				p.y += (v.x < 0) ? - offset : offset;
+				p.x += (v.y > 0) ? - offset : offset;
 				pts.push_back(p);
 			} 
 		}
diff --git a/xs/src/libslic3r/EdgeGrid.hpp b/xs/src/libslic3r/EdgeGrid.hpp
index 2473ce423..a0b23211e 100644
--- a/xs/src/libslic3r/EdgeGrid.hpp
+++ b/xs/src/libslic3r/EdgeGrid.hpp
@@ -58,7 +58,7 @@ public:
 	const size_t		cols() const { return m_cols; }
 
 	// For supports: Contours enclosing the rasterized edges.
-	Polygons 			contours_simplified() const;
+	Polygons 			contours_simplified(coord_t offset) const;
 
 protected:
 	struct Cell {
diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
index 3f7232e06..5122de144 100644
--- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp
+++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
@@ -882,7 +882,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
         Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
         // _align_to_grid will not work correctly with positive pattern_shift.
         coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
-        refpt.x -= (pattern_shift_scaled > 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
+        refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
         bounding_box.merge(_align_to_grid(
             bounding_box.min, 
             Point(line_spacing, line_spacing), 
@@ -892,7 +892,9 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
     // Intersect a set of euqally spaced vertical lines wiht expolygon.
     // n_vlines = ceil(bbox_width / line_spacing)
     size_t  n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing;
-    coord_t x0 = bounding_box.min.x + (line_spacing + SCALED_EPSILON) / 2;
+	coord_t x0 = bounding_box.min.x;
+	if (full_infill)
+		x0 += (line_spacing + SCALED_EPSILON) / 2;
 
 #ifdef SLIC3R_DEBUG
     static int iRun = 0;
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index f97f888cd..e8b0e0a03 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -159,6 +159,7 @@ public:
     void bridge_over_infill();
     void _make_perimeters();
     void _infill();
+    void _generate_support_material();
 
 private:
     Print* _print;
diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp
index 8d6ddaf21..3c92aad24 100644
--- a/xs/src/libslic3r/PrintObject.cpp
+++ b/xs/src/libslic3r/PrintObject.cpp
@@ -2,6 +2,7 @@
 #include "BoundingBox.hpp"
 #include "ClipperUtils.hpp"
 #include "Geometry.hpp"
+#include "SupportMaterial.hpp"
 
 #include <boost/log/trivial.hpp>
 
@@ -1243,4 +1244,10 @@ PrintObject::_infill()
     this->state.set_done(posInfill);
 }
 
+void PrintObject::_generate_support_material()
+{
+    PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
+    support_material.generate(*this);
+}
+
 } // namespace Slic3r
diff --git a/xs/src/libslic3r/Slicing.cpp b/xs/src/libslic3r/Slicing.cpp
index 0de781c64..5bd6bfc27 100644
--- a/xs/src/libslic3r/Slicing.cpp
+++ b/xs/src/libslic3r/Slicing.cpp
@@ -33,10 +33,18 @@ SlicingParameters SlicingParameters::create_from_config(
 
     SlicingParameters params;
     params.layer_height = object_config.layer_height.value;
+    params.first_print_layer_height = first_layer_height;
     params.first_object_layer_height = first_layer_height;
     params.object_print_z_min = 0.;
     params.object_print_z_max = object_height;
     params.base_raft_layers = object_config.raft_layers.value;
+    params.soluble_interface = soluble_interface;
+
+    if (! soluble_interface) {
+        params.gap_raft_object    = object_config.support_material_contact_distance.value;
+        params.gap_object_support = object_config.support_material_contact_distance.value;
+        params.gap_support_object = object_config.support_material_contact_distance.value;
+    }
 
     if (params.base_raft_layers > 0) {
 		params.interface_raft_layers = (params.base_raft_layers + 1) / 2;
@@ -70,18 +78,21 @@ SlicingParameters SlicingParameters::create_from_config(
     if (params.has_raft()) {
         // Raise first object layer Z by the thickness of the raft itself plus the extra distance required by the support material logic.
         //FIXME The last raft layer is the contact layer, which shall be printed with a bridging flow for ease of separation. Currently it is not the case.
-		coordf_t print_z = first_layer_height + object_config.support_material_contact_distance.value;
 		if (params.raft_layers() == 1) {
+            // There is only the contact layer.
 			params.contact_raft_layer_height = first_layer_height;
+            params.raft_contact_top_z = first_layer_height;
 		} else {
-			print_z +=
-				// Number of the base raft layers is decreased by the first layer, which has already been added to print_z.
-				coordf_t(params.base_raft_layers - 1) * params.base_raft_layer_height +
-				// Number of the interface raft layers is decreased by the contact layer.
-				coordf_t(params.interface_raft_layers - 1) * params.interface_raft_layer_height +
-				params.contact_raft_layer_height;
+            assert(params.base_raft_layers > 0);
+            assert(params.interface_raft_layers > 0);
+            // Number of the base raft layers is decreased by the first layer.
+            params.raft_base_top_z       = first_layer_height + coordf_t(params.base_raft_layers - 1) * params.base_raft_layer_height;
+            // Number of the interface raft layers is decreased by the contact layer.
+            params.raft_interface_top_z  = params.raft_base_top_z + coordf_t(params.interface_raft_layers - 1) * params.interface_raft_layer_height;
+			params.raft_contact_top_z    = params.raft_interface_top_z + params.contact_raft_layer_height;
 		}
-        params.object_print_z_min = print_z;
+        coordf_t print_z = params.raft_contact_top_z + params.gap_raft_object;
+        params.object_print_z_min  = print_z;
         params.object_print_z_max += print_z;
     }
 
diff --git a/xs/src/libslic3r/Slicing.hpp b/xs/src/libslic3r/Slicing.hpp
index 349be2e4a..02ae7dd9e 100644
--- a/xs/src/libslic3r/Slicing.hpp
+++ b/xs/src/libslic3r/Slicing.hpp
@@ -53,6 +53,10 @@ struct SlicingParameters
 	// or by the variable layer thickness table.
     coordf_t    layer_height;
 
+    // First layer height of the print, this may be used for the first layer of the raft
+    // or for the first layer of the print.
+    coordf_t    first_print_layer_height;
+
     // Thickness of the first layer. This is either the first print layer thickness if printed without a raft,
     // or a bridging flow thickness if printed over a non-soluble raft,
     // or a normal layer height if printed over a soluble raft.
@@ -61,6 +65,16 @@ struct SlicingParameters
     // If the object is printed over a non-soluble raft, the first layer may be printed with a briding flow.
     bool 		first_object_layer_bridging;
 
+    // Soluble interface? (PLA soluble in water, HIPS soluble in lemonen)
+    // otherwise the interface must be broken off.
+    bool        soluble_interface;
+    // Gap when placing object over raft.
+    coordf_t    gap_raft_object;
+    // Gap when placing support over object.
+    coordf_t    gap_object_support;
+    // Gap when placing object over support.
+    coordf_t    gap_support_object;
+
     // Minimum / maximum layer height, to be used for the automatic adaptive layer height algorithm,
     // or by an interactive layer height editor.
     coordf_t    min_layer_height;
@@ -69,6 +83,10 @@ struct SlicingParameters
     // Bottom and top of the printed object.
     // If printed without a raft, object_print_z_min = 0 and object_print_z_max = object height.
     // Otherwise object_print_z_min is equal to the raft height.
+    coordf_t    raft_base_top_z;
+    coordf_t    raft_interface_top_z;
+    coordf_t    raft_contact_top_z;
+    // In case of a soluble interface, object_print_z_min == raft_contact_top_z, otherwise there is a gap between the raft and the 1st object layer.
     coordf_t 	object_print_z_min;
     coordf_t 	object_print_z_max;
 };
diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp
index 8bf9e9fc7..7806e36a5 100644
--- a/xs/src/libslic3r/SupportMaterial.cpp
+++ b/xs/src/libslic3r/SupportMaterial.cpp
@@ -31,60 +31,35 @@ namespace Slic3r {
 #define PILLAR_SIZE (2.5)
 #define PILLAR_SPACING 10
 
-PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object) :
+PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) :
     m_object                (object),
     m_print_config          (&object->print()->config),
     m_object_config         (&object->config),
+    m_slicing_params        (slicing_params),
 
     m_first_layer_flow (Flow::new_from_config_width(
         frSupportMaterial,
+        // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
         (object->print()->config.first_layer_extrusion_width.value > 0) ? object->print()->config.first_layer_extrusion_width : object->config.support_material_extrusion_width,
         object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1),
-        object->config.get_abs_value("first_layer_height"),
+        slicing_params.first_print_layer_height,
         false
     )),
     m_support_material_flow (Flow::new_from_config_width(
         frSupportMaterial, 
+        // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
         (object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
         object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1),
-        object->config.layer_height.value,
+        slicing_params.layer_height,
         false)), 
     m_support_material_interface_flow(Flow::new_from_config_width(
         frSupportMaterialInterface,
-        (object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
+        // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
+        (object->config.support_material_extrusion_width > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
         object->print()->config.nozzle_diameter.get_at(object->config.support_material_interface_extruder-1),
         object->config.layer_height.value,
         false)),
-    m_soluble_interface (object->config.support_material_contact_distance.value == 0),
  
-    m_support_material_raft_base_flow(0, 0, 0, false),
-    m_support_material_raft_interface_flow(0, 0, 0, false),
-    m_support_material_raft_contact_flow(0, 0, 0, false),
-
-    m_has_raft                  (object->config.raft_layers.value > 0),
-    m_num_base_raft_layers      (0),
-    m_num_interface_raft_layers (0),
-    m_num_contact_raft_layers   (0),
-
-    // If set, the raft contact layer is laid with round strings, which are easily detachable
-    // from both the below and above layes.
-    // Otherwise a normal flow is used and the strings are squashed against the layer below, 
-    // creating a firm bond with the layer below and making the interface top surface flat.
-#if 1
-    // This is the standard Slic3r behavior.
-    m_raft_contact_layer_bridging(false),
-    m_object_1st_layer_bridging (true),
-#else
-    // This is more akin to what Simplify3D or Zortrax do.
-    m_raft_contact_layer_bridging(true),
-    m_object_1st_layer_bridging (false),
-#endif
-
-    m_raft_height               (0.),
-    m_raft_base_height          (0.),
-    m_raft_interface_height     (0.),
-    m_raft_contact_height       (0.),
-
     // 50 mirons layer
     m_support_layer_height_min  (0.05),
     m_support_layer_height_max  (0.),
@@ -101,79 +76,6 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
     // the support layers will be synchronized with the object layers exactly, no layer will be combined.
     m_combine_support_layers    (true)
 {
-    // Based on the raft style and size, initialize the raft layers and the 1st object layer attributes.
-
-    size_t num_raft_layers = m_object_config->raft_layers.value;
-
-    //FIXME better to draw thin strings, which are easier to remove from the object.
-    if (m_has_raft) 
-    {
-        if (m_raft_contact_layer_bridging)
-        m_support_material_raft_contact_flow = Flow::new_from_spacing(
-                m_support_material_raft_interface_flow.spacing(), 
-                m_support_material_raft_interface_flow.nozzle_diameter, 
-                m_support_material_raft_interface_flow.height, 
-                true);
-
-        if (m_raft_contact_layer_bridging && num_raft_layers == 1)
-            // The bridging contact layer will not bond to the bed well on its own.
-            // Ensure there is at least the 1st layer printed with a firm squash.
-            ++ num_raft_layers;
-
-        // Split the raft layers into a single contact layer
-        // and an equal number of interface and base layers,
-        // with m_num_interface_raft_layers >= m_num_base_raft_layers.
-        m_num_contact_raft_layers = 1;
-        m_num_interface_raft_layers = num_raft_layers / 2;
-        m_num_base_raft_layers = num_raft_layers - m_num_contact_raft_layers - m_num_interface_raft_layers;
-        assert(m_num_interface_raft_layers >= m_num_base_raft_layers);
-        assert(m_num_contact_raft_layers + m_num_base_raft_layers + m_num_interface_raft_layers == num_raft_layers);
-
-        m_raft_contact_height = m_num_contact_raft_layers * m_support_material_raft_contact_flow.height;
-        if (m_num_base_raft_layers > 0) {
-            m_raft_base_height = first_layer_height() + (m_num_base_raft_layers - 1) * m_support_material_raft_base_flow.height;
-            m_raft_interface_height = m_num_interface_raft_layers * m_support_material_raft_interface_flow.height;
-        } else if (m_num_interface_raft_layers > 0) {
-            m_raft_base_height = 0;
-            m_raft_interface_height = first_layer_height() + (m_num_interface_raft_layers - 1) * m_support_material_raft_interface_flow.height;
-        } else {
-            m_raft_base_height = 0;
-            m_raft_interface_height = 0;
-        }
-        m_raft_height = m_raft_base_height + m_raft_interface_height + m_raft_contact_height;
-
-        // Find the layer height of the 1st object layer.
-        if (m_object_1st_layer_bridging) {
-            // Use an average nozzle diameter.
-            std::set<size_t> extruders = m_object->print()->object_extruders();
-            coordf_t nozzle_dmr = 0;
-            for (std::set<size_t>::const_iterator it = extruders.begin(); it != extruders.end(); ++ it) {
-                nozzle_dmr += m_object->print()->config.nozzle_diameter.get_at(*it);
-            }
-            nozzle_dmr /= extruders.size();
-            m_object_1st_layer_height = nozzle_dmr;
-        } else {
-            m_object_1st_layer_height = m_object->config.layer_height.value;
-            for (t_layer_height_ranges::const_iterator it = m_object->layer_height_ranges.begin(); it != m_object->layer_height_ranges.end(); ++ it) {
-                if (m_object_1st_layer_height >= it->first.first && m_object_1st_layer_height <= it->first.second) {
-                    m_object_1st_layer_height = it->second;
-                    break;
-                }
-            }
-        }
-
-        m_object_1st_layer_gap = m_soluble_interface ? 0. : m_object_config->support_material_contact_distance.value;
-        m_object_1st_layer_print_z = m_raft_height + m_object_1st_layer_gap + m_object_1st_layer_height;
-    }
-    else
-    {
-        // No raft.
-        m_raft_contact_layer_bridging = false;
-        m_object_1st_layer_bridging  = false;
-        m_object_1st_layer_height    = m_first_layer_flow.height;
-        m_object_1st_layer_gap       = 0;
-        m_object_1st_layer_print_z   = m_object_1st_layer_height;
-    }
 }
 
 // Using the std::deque as an allocator.
@@ -286,7 +188,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
     // There is a contact layer below the 1st object layer in the bottom contacts.
     // There is also a 1st intermediate layer containing bases of support columns.
     // Extend the bases of the support columns and create the raft base.
-    Polygons raft = this->generate_raft_base(object, bottom_contacts, intermediate_layers);
+    MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, intermediate_layers, layer_storage);
 
 /*
     // If we wanted to apply some special logic to the first support layers lying on
@@ -323,7 +225,8 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
 
     // Install support layers into the object.
     MyLayersPtr layers_sorted;
-    layers_sorted.reserve(bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size());
+    layers_sorted.reserve(raft_layers.size() + bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size());
+    layers_append(layers_sorted, raft_layers);
     layers_append(layers_sorted, bottom_contacts);
     layers_append(layers_sorted, top_contacts);
     layers_append(layers_sorted, intermediate_layers);
@@ -351,7 +254,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
     BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths";
 
     // Generate the actual toolpaths and save them into each layer.
-    this->generate_toolpaths(object, raft, bottom_contacts, top_contacts, intermediate_layers, interface_layers);
+    this->generate_toolpaths(object, raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers);
 
     BOOST_LOG_TRIVIAL(info) << "Support generator - End";
 }
@@ -670,7 +573,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
             MyLayer     &new_layer   = layer_allocate(layer_storage, sltTopContact);
             const Layer *layer_below = (layer_id > 0) ? object.get_layer(layer_id - 1) : NULL;
             new_layer.idx_object_layer_above = layer_id;
-            if (m_soluble_interface) {
+            if (m_slicing_params.soluble_interface) {
                 // Align the contact surface height with a layer immediately below the supported layer.
                 new_layer.height = layer_below ? 
                     // Interface layer will be synchronized with the object.
@@ -984,16 +887,16 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
                     // Grow top surfaces so that interface and support generation are generated
                     // with some spacing from object - it looks we don't need the actual
                     // top shapes so this can be done here
-                    layer_new.height  = m_soluble_interface ? 
+                    layer_new.height  = m_slicing_params.soluble_interface ? 
                         // Align the interface layer with the object's layer height.
                         object.get_layer(layer_id + 1)->height :
                         // Place a bridge flow interface layer over the top surface.
                         m_support_material_interface_flow.nozzle_diameter;
                     layer_new.print_z = layer.print_z + layer_new.height + 
-                        (m_soluble_interface ? 0. : m_object_config->support_material_contact_distance.value);
+                        (m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value);
                     layer_new.bottom_z = layer.print_z;
                     layer_new.idx_object_layer_below = layer_id;
-                    layer_new.bridging = ! m_soluble_interface;
+                    layer_new.bridging = ! m_slicing_params.soluble_interface;
                     //FIXME how much to inflate the top surface?
                     layer_new.polygons = offset(touching, float(m_support_material_flow.scaled_width()));
         #ifdef SLIC3R_DEBUG
@@ -1011,7 +914,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
 
             // Create an EdgeGrid, initialize it with projection, initialize signed distance field.
             Slic3r::EdgeGrid::Grid grid;
-            coord_t grid_resolution = scale_(1.5f);
+            coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
+            coord_t grid_resolution = scale_(support_spacing); // scale_(1.5f);
             BoundingBox bbox = get_extents(projection);
             bbox.offset(20);
             bbox.align_to_grid(grid_resolution);
@@ -1020,7 +924,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
             grid.calculate_sdf();
 
             // Extract a bounding contour from the grid.
-            Polygons projection_simplified = grid.contours_simplified();
+            Polygons projection_simplified = grid.contours_simplified(-5);
 #ifdef SLIC3R_DEBUG
             {
                 BoundingBox bbox = get_extents(projection);
@@ -1031,12 +935,15 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
                 svg.draw(union_ex(projection_simplified, false), "red", 0.5);
             }
 #endif /* SLIC3R_DEBUG */
-            projection = std::move(projection_simplified);
+            layer_support_areas[layer_id] = diff(
+                grid.contours_simplified(m_support_material_flow.scaled_spacing()/2 + 5), 
+                to_polygons(layer.slices.expolygons),
+                true);
 
-            // Remove the areas that touched from the projection that will continue on next, lower, top surfaces. 
+            // Remove the areas that touched from the projection that will continue on next, lower, top surfaces.
             // projection = diff(projection, touching);
-            projection = diff(projection, to_polygons(layer.slices.expolygons), true);
-            layer_support_areas[layer_id] = projection;
+            projection = diff(projection_simplified, to_polygons(layer.slices.expolygons), true);
+//            layer_support_areas[layer_id] = projection;
         }
         std::reverse(bottom_contacts.begin(), bottom_contacts.end());
     } // ! top_contacts.empty()
@@ -1058,7 +965,7 @@ void PrintObjectSupportMaterial::trim_top_contacts_by_bottom_contacts(
         // For all top contact layers overlapping with the thick bottom contact layer:
         for (size_t idx_top = idx_top_first; idx_top < top_contacts.size(); ++ idx_top) {
             MyLayer &layer_top = *top_contacts[idx_top];
-            coordf_t interface_z = m_soluble_interface ? 
+            coordf_t interface_z = m_slicing_params.soluble_interface ? 
                 (layer_top.bottom_z + EPSILON) :
                 (layer_top.bottom_z - m_support_layer_height_min);
             if (interface_z < layer_bottom.print_z) {
@@ -1093,9 +1000,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
         return intermediate_layers;
     std::sort(extremes.begin(), extremes.end());
 
-    // Top of the 0th layer.
-    coordf_t top_z_0th = this->raft_base_height() + this->raft_interface_height();
-    assert(extremes.front().z() > top_z_0th && extremes.front().z() >= this->first_layer_height());
+	assert(extremes.front().z() > m_slicing_params.raft_interface_top_z && extremes.front().z() >= m_slicing_params.first_print_layer_height);
 
     // Generate intermediate layers.
     // The first intermediate layer is the same as the 1st layer if there is no raft,
@@ -1103,7 +1008,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
     // Intermediate layers are always printed with a normal etrusion flow (non-bridging).
     for (size_t idx_extreme = 0; idx_extreme < extremes.size(); ++ idx_extreme) {
         LayerExtreme *extr1  = (idx_extreme == 0) ? NULL : &extremes[idx_extreme-1];
-        coordf_t      extr1z = (extr1 == NULL) ? top_z_0th : extr1->z();
+        coordf_t      extr1z = (extr1 == NULL) ? m_slicing_params.raft_interface_top_z : extr1->z();
         LayerExtreme &extr2  = extremes[idx_extreme];
         coordf_t      extr2z = extr2.z();
         coordf_t      dist   = extr2z - extr1z;
@@ -1112,7 +1017,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
         size_t        n_layers_extra = size_t(ceil(dist / m_support_layer_height_max));
         assert(n_layers_extra > 0);
         coordf_t      step   = dist / coordf_t(n_layers_extra);
-        if (! m_soluble_interface && ! m_synchronize_support_layers_with_object && extr2.layer->layer_type == sltTopContact) {
+        if (! m_slicing_params.soluble_interface && ! m_synchronize_support_layers_with_object && extr2.layer->layer_type == sltTopContact) {
             assert(extr2.layer->height == 0.);
             // This is a top interface layer, which does not have a height assigned yet. Do it now.
             if (m_synchronize_support_layers_with_object) {
@@ -1345,43 +1250,74 @@ void PrintObjectSupportMaterial::generate_base_layers(
 #endif /* SLIC3R_DEBUG */
 }
 
-Polygons PrintObjectSupportMaterial::generate_raft_base(
+PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base(
     const PrintObject   &object,
-    const MyLayersPtr   &bottom_contacts,
-    MyLayersPtr         &intermediate_layers) const
+    const MyLayersPtr   &top_contacts,
+    MyLayersPtr         &intermediate_layers,
+    MyLayerStorage      &layer_storage) const
 {
-    assert(! bottom_contacts.empty());
-
+    // Areas covered by the raft, supporting the raft interface and the support columns.
     Polygons raft_polygons;
-    #if 0
+    // How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
     const float inflate_factor = scale_(3.);
-    if (this->has_raft()) {
-        MyLayer &contacts      = *bottom_contacts.front();
-        MyLayer &columns_base  = *intermediate_layers.front();
-        if (m_num_base_raft_layers == 0 && m_num_interface_raft_layers == 0 && m_num_contact_raft_layers == 1) {
-            // Having only the contact layer, which has the height of the 1st layer.
-            // We are free to merge the contacts with the columns_base, they will be printed the same way.
-            polygons_append(contacts.polygons, offset(columns_base.polygons, inflate_factor));
-            contacts.polygons = union_(contacts.polygons);
-        } else {
-            // Having multiple raft layers.
-            assert(m_num_interface_raft_layers > 0);
-            // Extend the raft base by the bases of the support columns, add the raft contacts.
-            raft_polygons = raft_interface_polygons;
-            //FIXME make the offset configurable.
-            polygons_append(raft_polygons, offset(columns_base.polygons, inflate_factor));
-            raft_polygons = union_(raft_polygons);
-        }
-    } else {
-        // No raft. The 1st intermediate layer contains the bases of the support columns.
-        // Expand the polygons, but trim with the object.
-        MyLayer &columns_base  = *intermediate_layers.front();
-        columns_base.polygons = diff(
-            offset(columns_base.polygons, inflate_factor),
-            offset(m_object->get_layer(0), safety_factor);
+    MyLayer *contacts      = top_contacts.empty() ? nullptr : top_contacts.front();
+    MyLayer *columns_base  = intermediate_layers.empty() ? nullptr : intermediate_layers.front();
+	if (contacts != nullptr && contacts->print_z > m_slicing_params.raft_contact_top_z + EPSILON)
+		// This is not the raft contact layer.
+		contacts = nullptr;
+
+	// Output vector.
+    MyLayersPtr raft_layers;
+
+    // Expand the 1st intermediate layer, which contains the bases of the support columns.
+	Polygons base;
+	if (columns_base != nullptr) {
+		base = offset(columns_base->polygons, inflate_factor);
+		// Modify the 1st intermediate layer with the expanded support columns.
+		columns_base->polygons = diff(
+			base,
+			offset(m_object->layers.front()->slices.expolygons, scale_(m_gap_xy)));
+		if (contacts != nullptr)
+			columns_base->polygons = diff(columns_base->polygons, contacts->polygons);
+	}
+    if (m_slicing_params.has_raft() && contacts != nullptr) {
+        // Merge the untrimmed columns base with the expanded raft interface, to be used for the support base and interface.
+        base = union_(base, offset(contacts->polygons, inflate_factor));
     }
-    #endif
-    return raft_polygons;
+	if (m_slicing_params.has_raft() && m_slicing_params.raft_layers() > 1 && ! base.empty()) {
+        // Do not add the raft contact layer, only add the raft layers below the contact layer.
+        // Insert the 1st layer.
+        {
+            MyLayer &new_layer = layer_allocate(layer_storage, (m_slicing_params.base_raft_layers > 0) ? sltRaftBase : sltRaftInterface);
+            raft_layers.push_back(&new_layer);
+            new_layer.print_z = m_slicing_params.first_print_layer_height;
+            new_layer.height  = m_slicing_params.first_print_layer_height;
+            new_layer.bottom_z = 0.;
+			new_layer.polygons = base;
+        }
+        // Insert the base layers.
+        for (size_t i = 1; i < m_slicing_params.base_raft_layers; ++ i) {
+			coordf_t print_z = raft_layers.back()->print_z;
+            MyLayer &new_layer  = layer_allocate(layer_storage, sltRaftBase);
+            raft_layers.push_back(&new_layer);
+			new_layer.print_z  = print_z + m_slicing_params.base_raft_layer_height;
+            new_layer.height   = m_slicing_params.base_raft_layer_height;
+			new_layer.bottom_z = print_z;
+			new_layer.polygons = base;
+		}
+        // Insert the interface layers.
+        for (size_t i = 1; i < m_slicing_params.interface_raft_layers; ++ i) {
+			coordf_t print_z = raft_layers.back()->print_z;
+			MyLayer &new_layer = layer_allocate(layer_storage, sltRaftInterface);
+            raft_layers.push_back(&new_layer);
+			new_layer.print_z = print_z + m_slicing_params.interface_raft_layer_height;
+            new_layer.height  = m_slicing_params.interface_raft_layer_height;
+			new_layer.bottom_z = print_z;
+			new_layer.polygons = base;
+		}
+    }
+
+    return raft_layers;
 }
 
 // Convert some of the intermediate layers into top/bottom interface layers.
@@ -1474,6 +1410,7 @@ static inline void fill_expolygons_generate_paths(
     FillParams fill_params;
     fill_params.density = density;
     fill_params.complete = true;
+    fill_params.dont_adjust = true;
     for (ExPolygons::const_iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++ it_expolygon) {
         Surface surface(stInternal, *it_expolygon);
         extrusion_entities_append_paths(
@@ -1495,6 +1432,7 @@ static inline void fill_expolygons_generate_paths(
     FillParams fill_params;
     fill_params.density = density;
     fill_params.complete = true;
+    fill_params.dont_adjust = true;
     for (ExPolygons::iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++ it_expolygon) {
         Surface surface(stInternal, std::move(*it_expolygon));
         extrusion_entities_append_paths(
@@ -1636,7 +1574,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
 
 void PrintObjectSupportMaterial::generate_toolpaths(
     const PrintObject   &object,
-    const Polygons      &raft,
+    const MyLayersPtr   &raft_layers,
     const MyLayersPtr   &bottom_contacts,
     const MyLayersPtr   &top_contacts,
     const MyLayersPtr   &intermediate_layers,
@@ -1667,7 +1605,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
     std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(ipRectilinear));
     std::unique_ptr<Fill> filler_support   = std::unique_ptr<Fill>(Fill::new_from_type(infill_pattern));
     {
-        BoundingBox bbox_object = object.bounding_box();
+//        BoundingBox bbox_object = object.bounding_box();
+        BoundingBox bbox_object(Point(-scale_(1.), -scale_(1.0)), Point(scale_(1.), scale_(1.)));
         filler_interface->set_bounding_box(bbox_object);
         filler_support->set_bounding_box(bbox_object);
     }
@@ -1694,12 +1633,64 @@ void PrintObjectSupportMaterial::generate_toolpaths(
         },
     );
     */
+    // Insert the raft base layers.
+    size_t support_layer_id = 0;
+    for (; support_layer_id < size_t(std::max(0, int(m_slicing_params.raft_layers()) - 1)); ++ support_layer_id) {
+        SupportLayer &support_layer = *object.support_layers[support_layer_id];
+        assert(support_layer_id < raft_layers.size());
+        MyLayer      &raft_layer    = *raft_layers[support_layer_id];
+        //FIXME When paralellizing, each thread shall have its own copy of the fillers.
+        Fill *filler = filler_support.get();
+        filler->angle = 0.;
+        // We don't use $base_flow->spacing because we need a constant spacing
+        // value that guarantees that all layers are correctly aligned.
+        Flow flow(m_support_material_flow.width, raft_layer.height, m_support_material_flow.nozzle_diameter, raft_layer.bridging);
+        filler->spacing = m_support_material_flow.spacing();
+        float density = support_density;
+        // find centerline of the external loop/extrusions
+        ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
+            // union_ex(base_polygons, true) :
+            offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON) :
+            offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
+        if (support_layer_id == 0) {
+            // Base flange.
+            filler = filler_interface.get();
+            filler->angle = m_object_config->support_material_angle + 90.;
+            density = 0.5f;
+            flow = m_first_layer_flow;
+            // use the proper spacing for first layer as we don't need to align
+            // its pattern to the other layers
+            //FIXME When paralellizing, each thread shall have its own copy of the fillers.
+            filler->spacing = flow.spacing();
+        } else if (with_sheath) {
+            // Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
+            // TODO: use brim ordering algorithm
+            Polygons to_infill_polygons = to_polygons(to_infill);
+            // TODO: use offset2_ex()
+            to_infill = offset_ex(to_infill, - flow.scaled_spacing());
+            extrusion_entities_append_paths(
+                support_layer.support_fills.entities, 
+                to_polylines(STDMOVE(to_infill_polygons)),
+                erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
+        }
+        fill_expolygons_generate_paths(
+            // Destination
+            support_layer.support_fills.entities, 
+            // Regions to fill
+            STDMOVE(to_infill), 
+            // Filler and its parameters
+            filler, density,
+            // Extrusion parameters
+            erSupportMaterial, flow);
+
+    }
+
     // Indices of the 1st layer in their respective container at the support layer height.
     size_t idx_layer_bottom_contact   = 0;
     size_t idx_layer_top_contact      = 0;
     size_t idx_layer_intermediate     = 0;
     size_t idx_layer_inteface         = 0;
-    for (size_t support_layer_id = 0; support_layer_id < object.support_layers.size(); ++ support_layer_id) 
+    for (; support_layer_id < object.support_layers.size(); ++ support_layer_id) 
     {
         SupportLayer &support_layer = *object.support_layers[support_layer_id];
 
@@ -1754,7 +1745,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
             // If no loops are allowed, we treat the contact layer exactly as a generic interface layer.
             if (interface_layer.could_merge(top_contact_layer))
                 interface_layer.merge(std::move(top_contact_layer));
-        }
+        } 
 
         if (! interface_layer.empty() && ! base_layer.empty()) {
             // turn base support into interface when it's contained in our holes
@@ -1814,7 +1805,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
             // We don't use $base_flow->spacing because we need a constant spacing
             // value that guarantees that all layers are correctly aligned.
             Flow flow(m_support_material_flow.width, base_layer.layer->height, m_support_material_flow.nozzle_diameter, base_layer.layer->bridging);
-            filler->spacing = flow.spacing();
+            filler->spacing = m_support_material_flow.spacing();
             float density = support_density;
             // find centerline of the external loop/extrusions
             ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
diff --git a/xs/src/libslic3r/SupportMaterial.hpp b/xs/src/libslic3r/SupportMaterial.hpp
index abcaf676a..c9cbee488 100644
--- a/xs/src/libslic3r/SupportMaterial.hpp
+++ b/xs/src/libslic3r/SupportMaterial.hpp
@@ -3,6 +3,7 @@
 
 #include "Flow.hpp"
 #include "PrintConfig.hpp"
+#include "Slicing.hpp"
 
 namespace Slic3r {
 
@@ -22,7 +23,8 @@ class PrintObjectSupportMaterial
 public:
 	enum SupporLayerType {
 		sltUnknown = 0,
-		sltRaft,
+		sltRaftBase,
+		sltRaftInterface,
 		stlFirstLayer,
 		sltBottomContact,
 		sltBottomInterface,
@@ -118,37 +120,17 @@ public:
 	typedef std::deque<MyLayer> 				MyLayerStorage;
 
 public:
-	PrintObjectSupportMaterial(const PrintObject *object);
+	PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params);
 
 	// Height of the 1st layer is user configured as it is important for the print
 	// to stick to he print bed.
 	coordf_t	first_layer_height() 		const { return m_object_config->first_layer_height.value; }
 
 	// Is raft enabled?
-	bool 		has_raft() 					const { return m_has_raft; }
+	bool 		has_raft() 					const { return m_slicing_params.has_raft(); }
 	// Has any support?
 	bool 		has_support()				const { return m_object_config->support_material.value; }
 
-	// How many raft layers are there below the 1st object layer?
-	// The 1st object layer_id will be offsetted by this number.
-	size_t 		num_raft_layers() 			const { return m_object_config->raft_layers.value; }
-	// num_raft_layers() == num_raft_base_layers() + num_raft_interface_layers() + num_raft_contact_layers().
-	size_t 		num_raft_base_layers() 		const { return m_num_base_raft_layers; }
-	size_t 		num_raft_interface_layers() const { return m_num_interface_raft_layers; }
-	size_t 		num_raft_contact_layers() 	const { return m_num_contact_raft_layers; }
-
-	coordf_t 	raft_height() 			    const { return m_raft_height; }
-	coordf_t    raft_base_height() 			const { return m_raft_base_height; }
-	coordf_t	raft_interface_height() 	const { return m_raft_interface_height; }
-	coordf_t	raft_contact_height() 		const { return m_raft_contact_height; }
-	bool 		raft_bridging() 			const { return m_raft_contact_layer_bridging; }
-
-	// 1st layer of the object will be printed depeding on the raft settings.
-	coordf_t 	first_object_layer_print_z() 	const { return m_object_1st_layer_print_z; }
-	coordf_t 	first_object_layer_height() 	const { return m_object_1st_layer_height; }
-	coordf_t 	first_object_layer_gap() 		const { return m_object_1st_layer_gap; }
-	bool 		first_object_layer_bridging() 	const { return m_object_1st_layer_bridging; }
-
 	// Generate support material for the object.
 	// New support layers will be added to the object,
 	// with extrusion paths and islands filled in for each support layer.
@@ -185,10 +167,11 @@ private:
 	    MyLayersPtr         &intermediate_layers,
 	    std::vector<Polygons> &layer_support_areas) const;
 
-    Polygons generate_raft_base(
+    MyLayersPtr generate_raft_base(
 	    const PrintObject   &object,
-	    const MyLayersPtr   &bottom_contacts,
-	    MyLayersPtr         &intermediate_layers) const;
+	    const MyLayersPtr   &top_contacts,
+	    MyLayersPtr         &intermediate_layers,
+	    MyLayerStorage	 	&layer_storage) const;
 
 	MyLayersPtr generate_interface_layers(
 	    const PrintObject   &object,
@@ -205,7 +188,7 @@ private:
 	// Produce the actual G-code.
 	void generate_toolpaths(
         const PrintObject   &object,
-        const Polygons 		&raft,
+        const MyLayersPtr 	&raft_layers,
         const MyLayersPtr   &bottom_contacts,
         const MyLayersPtr   &top_contacts,
         const MyLayersPtr   &intermediate_layers,
@@ -214,36 +197,14 @@ private:
 	const PrintObject 		*m_object;
 	const PrintConfig 		*m_print_config;
 	const PrintObjectConfig *m_object_config;
+	SlicingParameters	     m_slicing_params;
 
 	Flow 			 	 m_first_layer_flow;
 	Flow 			 	 m_support_material_flow;
+	coordf_t			 m_support_material_spacing;
 	Flow 			 	 m_support_material_interface_flow;
-	bool 			 	 m_soluble_interface;
+	coordf_t			 m_support_material_interface_spacing;
 
-	Flow 				 m_support_material_raft_base_flow;
-	Flow 				 m_support_material_raft_interface_flow;
-	Flow 				 m_support_material_raft_contact_flow;
-
-	bool 				 m_has_raft;
-	size_t 				 m_num_base_raft_layers;
-	size_t 				 m_num_interface_raft_layers;
-	size_t 				 m_num_contact_raft_layers;
-	// If set, the raft contact layer is laid with round strings, which are easily detachable
-	// from both the below and above layes.
-	// Otherwise a normal flow is used and the strings are squashed against the layer below, 
-	// creating a firm bond with the layer below and making the interface top surface flat.
-	coordf_t 			 m_raft_height;
-	coordf_t 			 m_raft_base_height;
-	coordf_t			 m_raft_interface_height;
-	coordf_t			 m_raft_contact_height;
-	bool 				 m_raft_contact_layer_bridging;
-
-	coordf_t 			 m_object_1st_layer_print_z;
-	coordf_t			 m_object_1st_layer_height;
-	coordf_t 			 m_object_1st_layer_gap;
-	bool 				 m_object_1st_layer_bridging;
-
-    coordf_t 			 m_object_layer_height_max;
     coordf_t 			 m_support_layer_height_min;
 	coordf_t		 	 m_support_layer_height_max;
 	coordf_t		 	 m_support_interface_layer_height_max;
diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp
index cfeae4ccc..70272fede 100644
--- a/xs/src/libslic3r/SurfaceCollection.cpp
+++ b/xs/src/libslic3r/SurfaceCollection.cpp
@@ -8,22 +8,12 @@ namespace Slic3r {
 
 SurfaceCollection::operator Polygons() const
 {
-    Polygons polygons;
-    for (Surfaces::const_iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
-        Polygons surface_p = surface->expolygon;
-        polygons.insert(polygons.end(), surface_p.begin(), surface_p.end());
-    }
-    return polygons;
+	return to_polygons(surfaces);
 }
 
 SurfaceCollection::operator ExPolygons() const
 {
-    ExPolygons expp;
-    expp.reserve(this->surfaces.size());
-    for (Surfaces::const_iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
-        expp.push_back(surface->expolygon);
-    }
-    return expp;
+	return to_expolygons(surfaces);
 }
 
 void
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 89db6d81e..d2a3c7c86 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -123,7 +123,7 @@ parallelize(std::queue<T> queue, boost::function<void(T)> func,
     if (threads_count == 0) threads_count = 2;
     boost::mutex queue_mutex;
     boost::thread_group workers;
-    for (int i = 0; i < fminf(threads_count, queue.size()); i++)
+    for (int i = 0; i < std::min(threads_count, int(queue.size())); ++ i)
         workers.add_thread(new boost::thread(&_parallelize_do<T>, &queue, &queue_mutex, func));
     workers.join_all();
 }
diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp
index 7461b9d91..4496f303c 100644
--- a/xs/xsp/Print.xsp
+++ b/xs/xsp/Print.xsp
@@ -119,6 +119,7 @@ _constant()
     void bridge_over_infill();
     void _make_perimeters();
     void _infill();
+    void _generate_support_material();
 
     void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
         %code%{ 
diff --git a/xs/xsp/SupportMaterial.xsp b/xs/xsp/SupportMaterial.xsp
deleted file mode 100644
index 01a53efa7..000000000
--- a/xs/xsp/SupportMaterial.xsp
+++ /dev/null
@@ -1,26 +0,0 @@
-%module{Slic3r::XS};
-
-%{
-#include <xsinit.h>
-#include "libslic3r/SupportMaterial.hpp"
-%}
-
-%name{Slic3r::Print::SupportMaterial2} class PrintObjectSupportMaterial {
-    PrintObjectSupportMaterial(PrintObject *print_object);
-    ~PrintObjectSupportMaterial();
-
-    void generate(PrintObject *object)
-        %code{% THIS->generate(*object); %};
-};
-
-%package{Slic3r::Print::SupportMaterial};
-%{
-
-SV*
-MARGIN()
-    PROTOTYPE:
-    CODE:
-        RETVAL = newSVnv(SUPPORT_MATERIAL_MARGIN);
-    OUTPUT: RETVAL
-
-%}