diff --git a/src/libs/vlayout/vlayoutgenerator.cpp b/src/libs/vlayout/vlayoutgenerator.cpp
index b4e6782df..396fedabe 100644
--- a/src/libs/vlayout/vlayoutgenerator.cpp
+++ b/src/libs/vlayout/vlayoutgenerator.cpp
@@ -35,7 +35,7 @@
 //---------------------------------------------------------------------------------------------------------------------
 VLayoutGenerator::VLayoutGenerator(QObject *parent)
     :QObject(parent), papers(QVector<VLayoutPaper>()), bank(new VBank()), paperHeight(0), paperWidth(0),
-      stopGeneration(false), state(LayoutErrors::NoError)
+      stopGeneration(false), state(LayoutErrors::NoError), shift(0)
 {}
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -88,6 +88,7 @@ void VLayoutGenerator::Generate()
             }
 
             VLayoutPaper paper(paperHeight, paperWidth);
+            paper.SetShift(shift);
             if (bank->LeftArrange() > 0)
             {
                 const int index = bank->GetTiket();
@@ -160,6 +161,18 @@ void VLayoutGenerator::SetPaperWidth(int value)
     paperWidth = value;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+unsigned int VLayoutGenerator::GetShift() const
+{
+    return shift;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VLayoutGenerator::SetShift(unsigned int shift)
+{
+    this->shift = shift;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 int VLayoutGenerator::GetPaperHeight() const
 {
@@ -171,4 +184,3 @@ void VLayoutGenerator::SetPaperHeight(int value)
 {
     paperHeight = value;
 }
-
diff --git a/src/libs/vlayout/vlayoutgenerator.h b/src/libs/vlayout/vlayoutgenerator.h
index b70fab62e..8ebfc8d89 100644
--- a/src/libs/vlayout/vlayoutgenerator.h
+++ b/src/libs/vlayout/vlayoutgenerator.h
@@ -55,6 +55,9 @@ public:
     int GetPaperWidth() const;
     void SetPaperWidth(int value);
 
+    unsigned int GetShift() const;
+    void         SetShift(unsigned int shift);
+
     void Generate();
 
     LayoutErrors State() const;
@@ -76,6 +79,7 @@ private:
     int paperWidth;
     bool stopGeneration;
     LayoutErrors state;
+    unsigned int shift;
 
     void CheckDetailsSize();
 };
diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp
index 7c9fd071b..3119ad74a 100644
--- a/src/libs/vlayout/vlayoutpaper.cpp
+++ b/src/libs/vlayout/vlayoutpaper.cpp
@@ -31,6 +31,7 @@
 
 #include <climits>
 #include <QPointF>
+#include <QtMath>
 
 class BestResult
 {
@@ -158,6 +159,18 @@ void VLayoutPaper::SetWidth(int width)
     d->paperWidth = width;
 }
 
+//---------------------------------------------------------------------------------------------------------------------
+unsigned int VLayoutPaper::GetShift() const
+{
+    return d->shift;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+void VLayoutPaper::SetShift(unsigned int shift)
+{
+    d->shift = shift;
+}
+
 //---------------------------------------------------------------------------------------------------------------------
 bool VLayoutPaper::ArrangeDetail(const VLayoutDetail &detail)
 {
@@ -193,36 +206,31 @@ bool VLayoutPaper::AddToBlankSheet(const VLayoutDetail &detail)
 {
     BestResult bestResult;
 
-    // We should use copy of the detail.
-    VLayoutDetail workDetail = detail;
-
-    for (int i=1; i<= detail.EdgesCount(); i++)
+    for (int j=1; j <= EdgesCount(); ++j)
     {
-        int dEdge = i;// For mirror detail edge will be different
-        if (CheckPosition(workDetail, 1, dEdge))
+        // We should use copy of the detail.
+        VLayoutDetail workDetail = detail;
+
+        for (int i=1; i<= detail.EdgesCount(); i++)
         {
-            const QRectF rec = workDetail.BoundingRect();
-            if (SheetContains(rec))
+            int dEdge = i;// For mirror detail edge will be different
+            if (CheckPosition(workDetail, j, dEdge))
             {
-                bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), 1, dEdge, workDetail.GetMatrix());
-            }
-            else
-            {
-                continue; // Outside of sheet.
+                const QRectF rec = workDetail.BoundingRect();
+                if (SheetContains(rec))
+                {
+                    bestResult.NewResult(static_cast<qint64>(rec.width()*rec.height()), j, dEdge,
+                                         workDetail.GetMatrix());
+                }
+                else
+                {
+                    continue; // Outside of sheet.
+                }
             }
         }
     }
 
-    if (bestResult.ValideResult())
-    {
-        VLayoutDetail workDetail = detail;
-        workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix
-        d->details.append(workDetail);
-        // First detail, just simple take all points
-        d->globalContour = workDetail.GetLayoutAllowencePoints();
-    }
-
-    return bestResult.ValideResult(); // Do we have the best result?
+    return SaveResult(bestResult, detail);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -256,22 +264,7 @@ bool VLayoutPaper::AddToSheet(const VLayoutDetail &detail)
         }
     }
 
-    if (bestResult.ValideResult())
-    {
-        VLayoutDetail workDetail = detail;
-        workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix
-        const QVector<QPointF> newGContour = UniteWithContour(workDetail, bestResult.GContourEdge(),
-                                                              bestResult.DetailEdge());
-        if (newGContour.isEmpty())
-        {
-            return false;
-        }
-        d->details.append(workDetail);
-        // First detail, just simple take all points
-        d->globalContour = newGContour;
-    }
-
-    return bestResult.ValideResult(); // Do we have the best result?
+    return SaveResult(bestResult, detail);
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -483,42 +476,63 @@ void VLayoutPaper::CombineEdges(VLayoutDetail &detail, const QLineF &globalEdge,
 //---------------------------------------------------------------------------------------------------------------------
 QVector<QPointF> VLayoutPaper::UniteWithContour(const VLayoutDetail &detail, int globalI, int detJ) const
 {
+    QVector<QPointF> newContour;
     if (d->globalContour.isEmpty())
     {
-        return detail.GetLayoutAllowencePoints();
-    }
-
-    if (globalI <= 0 || globalI > EdgesCount())
-    {
-        return QVector<QPointF>();
-    }
-
-    if (detJ <= 0 || detJ > detail.EdgesCount())
-    {
-        return QVector<QPointF>();
-    }
-
-    QVector<QPointF> newContour;
-    for(int i=0; i < d->globalContour.count(); ++i)
-    {
-        newContour.append(d->globalContour.at(i));
-        ++i;
-        if (i==globalI)
+        int processedEdges = 0;
+        const int nD = detail.EdgesCount();
+        int j = detJ+1;
+        do
         {
-            const QVector<QPointF> dPoints = detail.GetLayoutAllowencePoints();
-            const int nD = dPoints.count();
-            int processedPoints = 0;
-            int j = detJ;
-            do
+            if (j > nD)
             {
-                if (j > nD-1)
+                j=0;
+            }
+            const QVector<QPointF> points = CutEdge(detail.Edge(j));
+            for (int i = 0; i < points.size()-1; ++i)
+            {
+                newContour.append(points.at(i));
+            }
+            ++processedEdges;
+            ++j;
+        }while (processedEdges < nD);
+    }
+    else
+    {
+        if (globalI <= 0 || globalI > EdgesCount())
+        {
+            return QVector<QPointF>();
+        }
+
+        if (detJ <= 0 || detJ > detail.EdgesCount())
+        {
+            return QVector<QPointF>();
+        }
+
+        for(int i=0; i < d->globalContour.count(); ++i)
+        {
+            newContour.append(d->globalContour.at(i));
+            ++i;
+            if (i==globalI)
+            {
+                int processedEdges = 0;
+                const int nD = detail.EdgesCount();
+                int j = detJ+1;
+                do
                 {
-                    j=0;
-                }
-                newContour.append(dPoints.at(j));
-                ++processedPoints;
-                ++j;
-            }while (processedPoints<nD);
+                    if (j > nD)
+                    {
+                        j=0;
+                    }
+                    const QVector<QPointF> points = CutEdge(detail.Edge(j));
+                    for (int i = 0; i < points.size()-1; ++i)
+                    {
+                        newContour.append(points.at(i));
+                    }
+                    ++processedEdges;
+                    ++j;
+                }while (processedEdges < nD);
+            }
         }
     }
     return newContour;
@@ -530,29 +544,73 @@ QLineF VLayoutPaper::GlobalEdge(int i) const
     if (d->details.isEmpty())
     {
         // Because sheet is blank we have one global edge for all cases - Ox axis.
-        return QLineF(0, 0, d->paperWidth, 0);
-    }
+        const QLineF axis = QLineF(0, 0, d->paperWidth, 0);
+        if (d->shift == 0)
+        {
+            return axis;
+        }
 
-    if (i < 1 || i > EdgesCount())
-    { // Doesn't exist such edge
-        return QLineF();
-    }
-    QLineF edge;
-    if (i < EdgesCount())
-    {
-        edge = QLineF(d->globalContour.at(i-1), d->globalContour.at(i));
+        const int n = qFloor(axis.length()/d->shift);
+
+        if (i < 1 || i > n)
+        { // Doesn't exist such edge
+            return QLineF();
+        }
+
+        if (n <= 0)
+        {
+            return axis;
+        }
+        else
+        {
+            const qreal nShift = axis.length()/n;
+            return QLineF(nShift*(i-1), 0, nShift*i, 0);
+        }
     }
     else
-    { // Closed countour
-        edge = QLineF(d->globalContour.at(EdgesCount()-1), d->globalContour.at(0));
+    {
+        if (i < 1 || i > EdgesCount())
+        { // Doesn't exist such edge
+            return QLineF();
+        }
+        QLineF edge;
+        if (i < EdgesCount())
+        {
+            edge = QLineF(d->globalContour.at(i-1), d->globalContour.at(i));
+        }
+        else
+        { // Closed countour
+            edge = QLineF(d->globalContour.at(EdgesCount()-1), d->globalContour.at(0));
+        }
+        return edge;
     }
-    return edge;
 }
 
 //---------------------------------------------------------------------------------------------------------------------
 int VLayoutPaper::EdgesCount() const
 {
-    return d->globalContour.count();
+    if (d->details.isEmpty())
+    {
+        if (d->shift == 0)
+        {
+            return 1;
+        }
+
+        const QLineF axis = QLineF(0, 0, d->paperWidth, 0);
+        const int n = qFloor(axis.length()/d->shift);
+        if (n <= 0)
+        {
+            return 1;
+        }
+        else
+        {
+            return n;
+        }
+    }
+    else
+    {
+        return d->globalContour.count();
+    }
 }
 
 //---------------------------------------------------------------------------------------------------------------------
@@ -562,3 +620,53 @@ QPolygonF VLayoutPaper::GlobalPolygon() const
     points.append(points.first());
     return QPolygonF(points);
 }
+
+//---------------------------------------------------------------------------------------------------------------------
+QVector<QPointF> VLayoutPaper::CutEdge(const QLineF &edge) const
+{
+    QVector<QPointF> points;
+    if (d->shift == 0)
+    {
+        points.append(edge.p1());
+        points.append(edge.p2());
+    }
+
+    const int n = qFloor(edge.length()/d->shift);
+
+    if (n <= 0)
+    {
+        points.append(edge.p1());
+        points.append(edge.p2());
+    }
+    else
+    {
+        const qreal nShift = edge.length()/n;
+        for (int i = 1; i <= n+1; ++i)
+        {
+            QLineF l1 = edge;
+            l1.setLength(nShift*(i-1));
+            points.append(l1.p2());
+        }
+    }
+    return points;
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+bool VLayoutPaper::SaveResult(const BestResult &bestResult, const VLayoutDetail &detail)
+{
+    if (bestResult.ValideResult())
+    {
+        VLayoutDetail workDetail = detail;
+        workDetail.SetMatrix(bestResult.Matrix());// Don't forget set matrix
+        const QVector<QPointF> newGContour = UniteWithContour(workDetail, bestResult.GContourEdge(),
+                                                              bestResult.DetailEdge());
+        if (newGContour.isEmpty())
+        {
+            return false;
+        }
+        d->details.append(workDetail);
+        d->globalContour = newGContour;
+    }
+
+    return bestResult.ValideResult(); // Do we have the best result?
+}
diff --git a/src/libs/vlayout/vlayoutpaper.h b/src/libs/vlayout/vlayoutpaper.h
index 5e231fc0e..d22682be5 100644
--- a/src/libs/vlayout/vlayoutpaper.h
+++ b/src/libs/vlayout/vlayoutpaper.h
@@ -36,6 +36,7 @@ class VLayoutDetail;
 class QPointF;
 class QLineF;
 class QPolygonF;
+class BestResult;
 
 class VLayoutPaper
 {
@@ -52,6 +53,9 @@ public:
     int  GetWidth() const;
     void SetWidth(int width);
 
+    unsigned int GetShift() const;
+    void         SetShift(unsigned int shift);
+
     bool ArrangeDetail(const VLayoutDetail &detail);
     int  Count() const;
 private:
@@ -86,6 +90,9 @@ private:
     int    EdgesCount() const;
 
     QPolygonF GlobalPolygon() const;
+    QVector<QPointF> CutEdge(const QLineF &edge) const;
+
+    bool SaveResult(const BestResult &bestResult, const VLayoutDetail &detail);
 };
 
 #endif // VLAYOUTPAPER_H
diff --git a/src/libs/vlayout/vlayoutpaper_p.h b/src/libs/vlayout/vlayoutpaper_p.h
index 3a9e3b23b..523e7aec3 100644
--- a/src/libs/vlayout/vlayoutpaper_p.h
+++ b/src/libs/vlayout/vlayoutpaper_p.h
@@ -44,16 +44,17 @@ class VLayoutPaperData : public QSharedData
 {
 public:
     VLayoutPaperData()
-        :details(QVector<VLayoutDetail>()), globalContour(QVector<QPointF>()), paperHeight(0), paperWidth(0)
+        :details(QVector<VLayoutDetail>()), globalContour(QVector<QPointF>()), paperHeight(0), paperWidth(0), shift(0)
     {}
 
     VLayoutPaperData(int height, int width)
-        :details(QVector<VLayoutDetail>()), globalContour(QVector<QPointF>()), paperHeight(height), paperWidth(width)
+        :details(QVector<VLayoutDetail>()), globalContour(QVector<QPointF>()), paperHeight(height), paperWidth(width),
+          shift(0)
     {}
 
     VLayoutPaperData(const VLayoutPaperData &paper)
         :QSharedData(paper), details(paper.details), globalContour(paper.globalContour), paperHeight(paper.paperHeight),
-          paperWidth(paper.paperWidth)
+          paperWidth(paper.paperWidth), shift(paper.shift)
     {}
 
     ~VLayoutPaperData() {}
@@ -69,6 +70,8 @@ public:
 
     /** @brief paperWidth width of paper in pixels*/
     int paperWidth;
+
+    unsigned int shift;
 };
 
 #ifdef Q_CC_GNU