diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm
index 1d88b21c7..a35d99184 100644
--- a/lib/Slic3r/Layer.pm
+++ b/lib/Slic3r/Layer.pm
@@ -206,9 +206,10 @@ sub make_perimeters {
             $hole->reverse;
         }
         
-        # create other offsets
+        # generate perimeters inwards
+        my $loop_number = $Slic3r::perimeters + ($surface->additional_inner_perimeters || 0);
         push @perimeters, [];
-        for (my $loop = 0; $loop < $Slic3r::perimeters; $loop++) {
+        for (my $loop = 0; $loop < $loop_number; $loop++) {
             # offsetting a polygon can result in one or many offset polygons
             @last_offsets = map $_->offset_ex(-$distance), @last_offsets if $distance;
             last if !@last_offsets;
diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm
index 75bf7fb94..2a1aad22f 100644
--- a/lib/Slic3r/Print.pm
+++ b/lib/Slic3r/Print.pm
@@ -166,7 +166,7 @@ sub export_gcode {
     # this will add a set of extrusion loops to each layer
     # as well as generate infill boundaries
     $status_cb->(20, "Generating perimeters");
-    $_->make_perimeters for map @{$_->layers}, @{$self->objects};
+    $_->make_perimeters for @{$self->objects};
     
     # this will clip $layer->surfaces to the infill boundaries 
     # and split them in top/bottom/internal surfaces;
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index fea9ec586..5e403f8fd 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -157,6 +157,67 @@ sub cleanup {
     @{$self->layers} = ();
 }
 
+sub make_perimeters {
+    my $self = shift;
+    
+    # compare each layer to the one below, and mark those slices needing
+    # one additional inner perimeter, like the top of domed objects-
+    
+    # this algorithm makes sure that almost one perimeter is overlapping:
+    my $overlap = $Slic3r::flow_spacing;
+    
+    for my $layer_id (0 .. $self->layer_count-2) {
+        my $layer = $self->layers->[$layer_id];
+        my $upper_layer = $self->layers->[$layer_id+1];
+        
+        # compute polygons representing the thickness of the first external perimeter of
+        # the upper layer slices
+        my $upper = diff_ex(
+            [ map @$_, map $_->expolygon->offset_ex(+ 0.5 * scale $Slic3r::flow_spacing), @{$upper_layer->slices} ],
+            [ map @$_, map $_->expolygon->offset_ex(- scale($overlap) + (0.5 * scale $Slic3r::flow_spacing)), @{$upper_layer->slices} ],
+        );
+        next if !@$upper;
+        
+        # we need to limit our detection to the areas which would actually benefit from 
+        # more perimeters. so, let's compute the area we want to ignore
+        my $ignore = [];
+        {
+            my $diff = diff_ex(
+                [ map @$_, map $_->expolygon->offset_ex(- ($Slic3r::perimeters-0.5) * scale $Slic3r::flow_spacing), @{$layer->slices} ],
+                [ map @{$_->expolygon}, @{$upper_layer->slices} ],
+            );
+            $ignore = [ map @$_, map $_->offset_ex(scale $Slic3r::flow_spacing), @$diff ];
+        }
+        
+        foreach my $slice (@{$layer->slices}) {
+            my $hypothetical_perimeter_num = $Slic3r::perimeters + 1;
+            CYCLE: while (1) {
+                # compute polygons representing the thickness of the hypotetical new internal perimeter
+                # of our slice
+                my $hypothetical_perimeter;
+                {
+                    my $outer = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-1.5) * scale $Slic3r::flow_spacing) ];
+                    last CYCLE if !@$outer;
+                    my $inner = [ map @$_, $slice->expolygon->offset_ex(- ($hypothetical_perimeter_num-0.5) * scale $Slic3r::flow_spacing) ];
+                    last CYCLE if !@$inner;
+                    $hypothetical_perimeter = diff_ex($outer, $inner);
+                }
+                last CYCLE if !@$hypothetical_perimeter;
+                
+                
+                my $intersection = intersection_ex([ map @$_, @$upper ], [ map @$_, @$hypothetical_perimeter ]);
+                $intersection = diff_ex([ map @$_, @$intersection ], $ignore) if @$ignore;
+                last CYCLE if !@{ $intersection };
+                Slic3r::debugf "  adding one more perimeter at layer %d\n", $layer_id;
+                $slice->additional_inner_perimeters(($slice->additional_inner_perimeters || 0) + 1);
+                $hypothetical_perimeter_num++;
+            }
+        }
+    }
+    
+    $_->make_perimeters for @{$self->layers};
+}
+
 sub detect_surfaces_type {
     my $self = shift;
     Slic3r::debugf "Detecting solid surfaces...\n";
diff --git a/lib/Slic3r/Surface.pm b/lib/Slic3r/Surface.pm
index 783501dfc..95f3da490 100644
--- a/lib/Slic3r/Surface.pm
+++ b/lib/Slic3r/Surface.pm
@@ -6,13 +6,14 @@ use constant S_EXPOLYGON    => 0;
 use constant S_SURFACE_TYPE => 1;
 use constant S_DEPTH_LAYERS => 2;
 use constant S_BRIDGE_ANGLE => 3;
+use constant S_ADDITIONAL_INNER_PERIMETERS => 4;
 
 sub new {
     my $class = shift;
     my %args = @_;
     
     my $self = [
-        map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle),
+        map delete $args{$_}, qw(expolygon surface_type depth_layers bridge_angle additional_inner_perimeters),
     ];
     $self->[S_DEPTH_LAYERS] //= 1; #/
     
@@ -24,6 +25,7 @@ sub expolygon       { $_[0][S_EXPOLYGON] }
 sub surface_type    { $_[0][S_SURFACE_TYPE] = $_[1] if $_[1]; $_[0][S_SURFACE_TYPE] }
 sub depth_layers    { $_[0][S_DEPTH_LAYERS] } # this integer represents the thickness of the surface expressed in layers
 sub bridge_angle    { $_[0][S_BRIDGE_ANGLE] }
+sub additional_inner_perimeters { $_[0][S_ADDITIONAL_INNER_PERIMETERS] = $_[1] if $_[1]; $_[0][S_ADDITIONAL_INNER_PERIMETERS] }
 
 # delegate handles
 sub encloses_point  { $_[0]->expolygon->encloses_point }