diff --git a/src/libslic3r/BridgeDetector.cpp b/src/libslic3r/BridgeDetector.cpp
index ff33e81d5..671ebbdaa 100644
--- a/src/libslic3r/BridgeDetector.cpp
+++ b/src/libslic3r/BridgeDetector.cpp
@@ -40,7 +40,7 @@ void BridgeDetector::initialize()
     this->angle = -1.;
 
     // Outset our bridge by an arbitrary amout; we'll use this outer margin for detecting anchors.
-    Polygons grown = offset(to_polygons(this->expolygons), float(this->spacing));
+    Polygons grown = offset(this->expolygons, float(this->spacing));
     
     // Detect possible anchoring edges of this bridging region.
     // Detect what edges lie on lower slices by turning bridge contour and holes
diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp
index c1b887583..6668a9ae9 100644
--- a/src/libslic3r/ClipperUtils.hpp
+++ b/src/libslic3r/ClipperUtils.hpp
@@ -12,6 +12,8 @@ using ClipperLib::jtMiter;
 using ClipperLib::jtRound;
 using ClipperLib::jtSquare;
 
+#define CLIPPERUTILS_UNSAFE_OFFSET
+
 // #define CLIPPERUTILS_OFFSET_SCALE
 
 #ifdef CLIPPERUTILS_OFFSET_SCALE
@@ -51,8 +53,11 @@ ClipperLib::Paths _offset(ClipperLib::Path &&input, ClipperLib::EndType endType,
 ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit);
 inline Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter,  double miterLimit = 3)
     { return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
+
+#ifdef CLIPPERUTILS_UNSAFE_OFFSET
 inline Slic3r::Polygons offset(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
     { return ClipperPaths_to_Slic3rPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
+#endif // CLIPPERUTILS_UNSAFE_OFFSET
 
 // offset Polylines
 inline Slic3r::Polygons offset(const Slic3r::Polyline &polyline, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtSquare, double miterLimit = 3)
@@ -69,13 +74,18 @@ inline Slic3r::Polygons offset(const Slic3r::ExPolygons &expolygons, const float
     { return ClipperPaths_to_Slic3rPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
 inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygon &polygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
     { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoint_to_ClipperPath(polygon), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }    
+
+#ifdef CLIPPERUTILS_UNSAFE_OFFSET
 inline Slic3r::ExPolygons offset_ex(const Slic3r::Polygons &polygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
     { return ClipperPaths_to_Slic3rExPolygons(_offset(Slic3rMultiPoints_to_ClipperPaths(polygons), ClipperLib::etClosedPolygon, delta, joinType, miterLimit)); }
+#endif // CLIPPERUTILS_UNSAFE_OFFSET
+
 inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
     { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygon, delta, joinType, miterLimit)); }
 inline Slic3r::ExPolygons offset_ex(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType = ClipperLib::jtMiter, double miterLimit = 3)
     { return ClipperPaths_to_Slic3rExPolygons(_offset(expolygons, delta, joinType, miterLimit)); }
 
+#ifdef CLIPPERUTILS_UNSAFE_OFFSET
 ClipperLib::Paths _offset2(const Slic3r::Polygons &polygons, const float delta1,
     const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, 
     double miterLimit = 3);
@@ -85,6 +95,8 @@ Slic3r::Polygons offset2(const Slic3r::Polygons &polygons, const float delta1,
 Slic3r::ExPolygons offset2_ex(const Slic3r::Polygons &polygons, const float delta1,
     const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, 
     double miterLimit = 3);
+#endif // CLIPPERUTILS_UNSAFE_OFFSET
+
 Slic3r::ExPolygons offset2_ex(const Slic3r::ExPolygons &expolygons, const float delta1,
     const float delta2, ClipperLib::JoinType joinType = ClipperLib::jtMiter, 
     double miterLimit = 3);
@@ -323,6 +335,7 @@ void safety_offset(ClipperLib::Paths* paths);
 
 Polygons top_level_islands(const Slic3r::Polygons &polygons);
 
+ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector<float> &deltas, double miter_limit);
 Polygons  variable_offset_inner(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
 Polygons  variable_offset_outer(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
 ExPolygons variable_offset_outer_ex(const ExPolygon &expoly, const std::vector<std::vector<float>> &deltas, double miter_limit = 2.);
diff --git a/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp
index 46b3a3a1b..73770bb18 100644
--- a/src/libslic3r/ExPolygon.hpp
+++ b/src/libslic3r/ExPolygon.hpp
@@ -217,6 +217,28 @@ inline Polygons to_polygons(const ExPolygons &src)
     return polygons;
 }
 
+inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygon &src)
+{
+    ConstPolygonPtrs polygons;
+    polygons.reserve(src.holes.size() + 1);
+    polygons.emplace_back(&src.contour);
+    for (const Polygon &hole : src.holes)
+        polygons.emplace_back(&hole);
+    return polygons;
+}
+
+inline ConstPolygonPtrs to_polygon_ptrs(const ExPolygons &src)
+{
+    ConstPolygonPtrs polygons;
+    polygons.reserve(number_polygons(src));
+    for (const ExPolygon &expoly : src) {
+        polygons.emplace_back(&expoly.contour);
+        for (const Polygon &hole : expoly.holes)
+            polygons.emplace_back(&hole);
+    }
+    return polygons;
+}
+
 inline Polygons to_polygons(ExPolygon &&src)
 {
     Polygons polygons;
diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp
index 1b96c43a4..785c93be3 100644
--- a/src/libslic3r/Fill/FillConcentric.cpp
+++ b/src/libslic3r/Fill/FillConcentric.cpp
@@ -24,11 +24,11 @@ void FillConcentric::_fill_surface_single(
         this->spacing = unscale<double>(distance);
     }
 
-    Polygons loops = to_polygons(std::move(expolygon));
-    Polygons last  = loops;
+    Polygons   loops = to_polygons(expolygon);
+    ExPolygons last { std::move(expolygon) };
     while (! last.empty()) {
-        last = offset2(last, -(distance + min_spacing/2), +min_spacing/2);
-        append(loops, last);
+        last = offset2_ex(last, -(distance + min_spacing/2), +min_spacing/2);
+        append(loops, to_polygons(last));
     }
 
     // generate paths from the outermost to the innermost, to avoid
diff --git a/src/libslic3r/Fill/FillLine.cpp b/src/libslic3r/Fill/FillLine.cpp
index 6a0a19efd..f6431a333 100644
--- a/src/libslic3r/Fill/FillLine.cpp
+++ b/src/libslic3r/Fill/FillLine.cpp
@@ -58,7 +58,7 @@ void FillLine::_fill_surface_single(
         pts.push_back(it->a);
         pts.push_back(it->b);
     }
-    Polylines polylines = intersection_pl(polylines_src, offset(to_polygons(expolygon), scale_(0.02)), false);
+    Polylines polylines = intersection_pl(polylines_src, offset(expolygon, scale_(0.02)), false);
 
     // FIXME Vojtech: This is only performed for horizontal lines, not for the vertical lines!
     const float INFILL_OVERLAP_OVER_SPACING = 0.3f;
diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp
index f6c0c9c7a..059d94e25 100644
--- a/src/libslic3r/LayerRegion.cpp
+++ b/src/libslic3r/LayerRegion.cpp
@@ -216,7 +216,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
                         break;
                     }
                 // Grown by 3mm.
-                Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
+                Polygons polys = offset(bridges[i].expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
                 if (idx_island == -1) {
 				    BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
                 } else {
diff --git a/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp
index aa72b4244..dd2d68d46 100644
--- a/src/libslic3r/Polygon.hpp
+++ b/src/libslic3r/Polygon.hpp
@@ -11,7 +11,9 @@
 namespace Slic3r {
 
 class Polygon;
-typedef std::vector<Polygon> Polygons;
+using Polygons          = std::vector<Polygon>;
+using PolygonPtrs       = std::vector<Polygon*>;
+using ConstPolygonPtrs  = std::vector<const Polygon*>;
 
 class Polygon : public MultiPoint
 {
diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp
index d5a349087..f8fa1ca17 100644
--- a/src/libslic3r/TriangleMesh.cpp
+++ b/src/libslic3r/TriangleMesh.cpp
@@ -511,20 +511,22 @@ void TriangleMesh::merge(const TriangleMesh &mesh)
 //FIXME This could be extremely slow! Use it for tiny meshes only!
 ExPolygons TriangleMesh::horizontal_projection() const
 {
-    Polygons pp;
-    pp.reserve(this->stl.stats.number_of_facets);
+    ClipperLib::Paths   paths;
+    Polygon             p;
+    p.points.assign(3, Point());
+    auto                delta = scaled<float>(0.01);
+    std::vector<float>  deltas { delta, delta, delta };
+    paths.reserve(this->stl.stats.number_of_facets);
 	for (const stl_facet &facet : this->stl.facet_start) {
-        Polygon p;
-        p.points.resize(3);
         p.points[0] = Point::new_scale(facet.vertex[0](0), facet.vertex[0](1));
         p.points[1] = Point::new_scale(facet.vertex[1](0), facet.vertex[1](1));
         p.points[2] = Point::new_scale(facet.vertex[2](0), facet.vertex[2](1));
-        p.make_counter_clockwise();  // do this after scaling, as winding order might change while doing that
-        pp.emplace_back(p);
+        p.make_counter_clockwise();
+        paths.emplace_back(mittered_offset_path_scaled(p.points, deltas, 3.));
     }
     
     // the offset factor was tuned using groovemount.stl
-    return union_ex(offset(pp, scale_(0.01)), true);
+    return ClipperPaths_to_Slic3rExPolygons(paths);
 }
 
 // 2D convex hull of a 3D mesh projected into the Z=0 plane.
@@ -1797,7 +1799,7 @@ void TriangleMeshSlicer::make_expolygons(const Polygons &loops, const float clos
     
     // append to the supplied collection
     if (safety_offset > 0)
-        expolygons_append(*slices, offset2_ex(union_(loops, false), +safety_offset, -safety_offset));
+        expolygons_append(*slices, offset2_ex(union_ex(loops, false), +safety_offset, -safety_offset));
     else
         expolygons_append(*slices, union_ex(loops, false));
 }