diff --git a/toonz/sources/include/toonz/rasterstrokegenerator.h b/toonz/sources/include/toonz/rasterstrokegenerator.h
index 4b3f7ff..e2c7857 100644
--- a/toonz/sources/include/toonz/rasterstrokegenerator.h
+++ b/toonz/sources/include/toonz/rasterstrokegenerator.h
@@ -67,7 +67,7 @@ public:
   void add(const TThickPoint &p);
 
   // Disegna il tratto interamente
-  void generateStroke(bool isPencil) const;
+  void generateStroke(bool isPencil, bool isStraight = false) const;
 
   // Ritorna m_points
   std::vector<TThickPoint> getPointsSequence() { return m_points; }
@@ -79,7 +79,8 @@ public:
   // raggio "points.thick" +2 pixel a bordo
   TRect getBBox(const std::vector<TThickPoint> &points) const;
 
-  TRect getLastRect() const;
+  TRect getLastRect(bool isStraight = false) const;
 
-  TRect generateLastPieceOfStroke(bool isPencil, bool closeStroke = false);
+  TRect generateLastPieceOfStroke(bool isPencil, bool closeStroke = false,
+                                  bool isStraight = false);
 };
diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp
index 9f1bf7b..c6f480b 100644
--- a/toonz/sources/tnztools/fullcolorbrushtool.cpp
+++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp
@@ -317,6 +317,13 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
 
   if (!ri) return;
 
+  // Modifier to do straight line
+  if (e.isShiftPressed() || e.isCtrlPressed()) {
+    m_isStraight = true;
+    m_firstPoint = pos;
+    m_lastPoint  = pos;
+  }
+
   /* update color here since the current style might be switched with numpad
    * shortcut keys */
   updateCurrentStyle();
@@ -364,6 +371,9 @@ void FullColorBrushTool::leftButtonDown(const TPointD &pos,
 
 void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
                                         const TMouseEvent &e) {
+  TRectD invalidateRect;
+  m_lastPoint = pos;
+
   TPointD previousBrushPos = m_brushPos;
   m_brushPos = m_mousePos = pos;
   m_mouseEvent            = e;
@@ -382,6 +392,46 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
   else
     pressure = m_enabledPressure ? e.m_pressure : 1.0;
 
+  if (m_maxPressure < pressure) m_maxPressure = pressure;
+
+  if (m_isStraight) {
+    invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
+    if (e.isCtrlPressed()) {
+      double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
+      TRectD brushRect =
+          TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
+                 TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
+      invalidateRect += (brushRect);
+      double denominator = m_lastPoint.x - m_firstPoint.x;
+      if (denominator == 0) denominator == 0.001;
+      double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
+      double angle = std::atan(slope) * (180 / 3.14159);
+      if (abs(angle) > 67.5)
+        m_lastPoint.x = m_firstPoint.x;
+      else if (abs(angle) < 22.5)
+        m_lastPoint.y = m_firstPoint.y;
+      else {
+        double xDistance = m_lastPoint.x - m_firstPoint.x;
+        double yDistance = m_lastPoint.y - m_firstPoint.y;
+        if (abs(xDistance) > abs(yDistance)) {
+          if (abs(yDistance) == yDistance)
+            m_lastPoint.y = m_firstPoint.y + abs(xDistance);
+          else
+            m_lastPoint.y = m_firstPoint.y - abs(xDistance);
+        } else {
+          if (abs(xDistance) == xDistance)
+            m_lastPoint.x = m_firstPoint.x + abs(yDistance);
+          else
+            m_lastPoint.x = m_firstPoint.x - abs(yDistance);
+        }
+      }
+    }
+    m_mousePos = pos;
+    m_brushPos = pos;
+    invalidate(invalidateRect);
+    return;
+  }
+
   m_strokeSegmentRect.empty();
   m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
   TRect updateRect = m_strokeSegmentRect * ras->getBounds();
@@ -389,7 +439,7 @@ void FullColorBrushTool::leftButtonDrag(const TPointD &pos,
     ras->extract(updateRect)->copy(m_workRaster->extract(updateRect));
 
   TPointD thickOffset(m_maxCursorThick * 0.5, m_maxCursorThick * 0.5);
-  TRectD invalidateRect = convert(m_strokeSegmentRect) - rasCenter;
+  invalidateRect = convert(m_strokeSegmentRect) - rasCenter;
   invalidateRect += TRectD(m_brushPos - thickOffset, m_brushPos + thickOffset);
   invalidateRect +=
       TRectD(previousBrushPos - thickOffset, previousBrushPos + thickOffset);
@@ -410,7 +460,11 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
 
   TRasterP ras      = ri->getRaster();
   TPointD rasCenter = ras->getCenterD();
-  TPointD point(pos + rasCenter);
+  TPointD point;
+  if (m_isStraight)
+    point = TPointD(m_lastPoint + rasCenter);
+  else
+    point = TPointD(pos + rasCenter);
   double pressure;
   if (getApplication()->getCurrentLevelStyle()->getTagId() ==
       4001)  // mypaint brush case
@@ -418,6 +472,10 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
   else
     pressure = m_enabledPressure ? e.m_pressure : 1.0;
 
+  if (m_isStraight && m_maxPressure > 0.0) {
+    pressure = m_maxPressure;
+  }
+
   m_strokeSegmentRect.empty();
   m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
   m_toonz_brush->endStroke();
@@ -455,6 +513,8 @@ void FullColorBrushTool::leftButtonUp(const TPointD &pos,
   notifyImageChanged();
   m_strokeRect.empty();
   m_mousePressed = false;
+  m_isStraight   = false;
+  m_maxPressure  = -1.0;
 }
 
 //---------------------------------------------------------------------------------------------------------------
@@ -522,6 +582,11 @@ void FullColorBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
 
 void FullColorBrushTool::draw() {
   if (TRasterImageP ri = TRasterImageP(getImage(false))) {
+    // Draw line segment on straight line mode
+    if (m_isStraight) {
+      tglDrawSegment(m_firstPoint, m_lastPoint);
+    }
+
     // If toggled off, don't draw brush outline
     if (!Preferences::instance()->isCursorOutlineEnabled()) return;
 
diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h
index 414aff9..23f5b58 100644
--- a/toonz/sources/tnztools/fullcolorbrushtool.h
+++ b/toonz/sources/tnztools/fullcolorbrushtool.h
@@ -123,6 +123,11 @@ protected:
   bool m_mousePressed = false;
   TMouseEvent m_mouseEvent;
 
+  bool m_isStraight = false;
+  TPointD m_firstPoint;
+  TPointD m_lastPoint;
+  double m_maxPressure = -1.0;
+
   bool m_propertyUpdating = false;
 };
 
diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
index db1db72..a6f8cf4 100644
--- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
@@ -437,18 +437,21 @@ class RasterBrushUndo final : public TRasterUndo {
   bool m_selective;
   bool m_isPaletteOrder;
   bool m_isPencil;
+  bool m_isStraight;
   bool m_modifierLockAlpha;
 
 public:
   RasterBrushUndo(TTileSetCM32 *tileSet, const std::vector<TThickPoint> &points,
                   int styleId, bool selective, TXshSimpleLevel *level,
                   const TFrameId &frameId, bool isPencil, bool isFrameCreated,
-                  bool isLevelCreated, bool isPaletteOrder, bool lockAlpha)
+                  bool isLevelCreated, bool isPaletteOrder, bool lockAlpha,
+                  bool isStraight = false)
       : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0)
       , m_points(points)
       , m_styleId(styleId)
       , m_selective(selective)
       , m_isPencil(isPencil)
+      , m_isStraight(isStraight)
       , m_isPaletteOrder(isPaletteOrder)
       , m_modifierLockAlpha(lockAlpha) {}
 
@@ -465,7 +468,7 @@ public:
       m_rasterTrack.setAboveStyleIds(aboveStyleIds);
     }
     m_rasterTrack.setPointsSequence(m_points);
-    m_rasterTrack.generateStroke(m_isPencil);
+    m_rasterTrack.generateStroke(m_isPencil, m_isStraight);
     image->setSavebox(image->getSavebox() +
                       m_rasterTrack.getBBox(m_rasterTrack.getPointsSequence()));
     ToolUtils::updateSaveBox();
@@ -488,6 +491,7 @@ class RasterBluredBrushUndo final : public TRasterUndo {
   DrawOrder m_drawOrder;
   int m_maxThick;
   double m_hardness;
+  bool m_isStraight;
   bool m_modifierLockAlpha;
 
 public:
@@ -496,12 +500,13 @@ public:
                         DrawOrder drawOrder, bool lockAlpha,
                         TXshSimpleLevel *level, const TFrameId &frameId,
                         int maxThick, double hardness, bool isFrameCreated,
-                        bool isLevelCreated)
+                        bool isLevelCreated, bool isStraight = false)
       : TRasterUndo(tileSet, level, frameId, isFrameCreated, isLevelCreated, 0)
       , m_points(points)
       , m_styleId(styleId)
       , m_drawOrder(drawOrder)
       , m_maxThick(maxThick)
+      , m_isStraight(isStraight)
       , m_hardness(hardness)
       , m_modifierLockAlpha(lockAlpha) {}
 
@@ -528,7 +533,16 @@ public:
     brush.addPoint(m_points[0], 1);
     brush.updateDrawing(ras, ras, bbox, m_styleId, (int)m_drawOrder,
                         m_modifierLockAlpha);
-    if (m_points.size() > 1) {
+    if (m_isStraight) {
+      points.clear();
+      points.push_back(m_points[0]);
+      points.push_back(m_points[1]);
+      points.push_back(m_points[2]);
+      bbox = brush.getBoundFromPoints(points);
+      brush.addArc(m_points[0], m_points[1], m_points[2], 1, 1);
+      brush.updateDrawing(ras, backupRas, bbox, m_styleId, (int)m_drawOrder,
+                          m_modifierLockAlpha);
+    } else if (m_points.size() > 1) {
       points.clear();
       points.push_back(m_points[0]);
       points.push_back(m_points[1]);
@@ -613,6 +627,7 @@ double computeThickness(double pressure, const TDoublePairProperty &property) {
   double t      = pressure * pressure * pressure;
   double thick0 = property.getValue().first;
   double thick1 = property.getValue().second;
+
   if (thick1 < 0.0001) thick0 = thick1 = 0.0;
   return (thick0 + (thick1 - thick0) * t) * 0.5;
 }
@@ -1272,6 +1287,13 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
     }
   }
 
+  // Modifier to do straight line
+  if (e.isShiftPressed() || e.isCtrlPressed()) {
+    m_isStraight = true;
+    m_firstPoint = pos;
+    m_lastPoint  = pos;
+  }
+
   // assert(0<=m_styleId && m_styleId<2);
   TImageP img = getImage(true);
   TToonzImageP ri(img);
@@ -1312,6 +1334,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
       TPointD point(centeredPos + rasCenter);
       double pressure =
           m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
+
       updateCurrentStyle();
       if (!(m_workRas && m_backupRas)) setWorkAndBackupImages();
       m_workRas->lock();
@@ -1412,13 +1435,54 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
 
 void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
                                           const TMouseEvent &e) {
+  TRectD invalidateRect;
+  m_lastPoint = pos;
+
   if (!m_enabled || !m_active) {
     m_mousePos = pos;
     m_brushPos = getCenteredCursorPos(pos);
     return;
   }
 
-  TPointD centeredPos = getCenteredCursorPos(pos);
+  if (m_isStraight) {
+    invalidateRect = TRectD(m_firstPoint, m_lastPoint).enlarge(2);
+    if (e.isCtrlPressed()) {
+      double distance = (m_brushPos.x - m_maxCursorThick + 1) * 0.5;
+      TRectD brushRect =
+          TRectD(TPointD(m_brushPos.x - distance, m_brushPos.y - distance),
+                 TPointD(m_brushPos.x + distance, m_brushPos.y + distance));
+      invalidateRect += (brushRect);
+      double denominator = m_lastPoint.x - m_firstPoint.x;
+      if (denominator == 0) denominator == 0.001;
+      double slope = ((m_lastPoint.y - m_firstPoint.y) / denominator);
+      double angle = std::atan(slope) * (180 / 3.14159);
+      if (abs(angle) > 67.5)
+        m_lastPoint.x = m_firstPoint.x;
+      else if (abs(angle) < 22.5)
+        m_lastPoint.y = m_firstPoint.y;
+      else {
+        double xDistance = m_lastPoint.x - m_firstPoint.x;
+        double yDistance = m_lastPoint.y - m_firstPoint.y;
+        if (abs(xDistance) > abs(yDistance)) {
+          if (abs(yDistance) == yDistance)
+            m_lastPoint.y = m_firstPoint.y + abs(xDistance);
+          else
+            m_lastPoint.y = m_firstPoint.y - abs(xDistance);
+        } else {
+          if (abs(xDistance) == xDistance)
+            m_lastPoint.x = m_firstPoint.x + abs(yDistance);
+          else
+            m_lastPoint.x = m_firstPoint.x - abs(yDistance);
+        }
+      }
+    }
+    m_mousePos = pos;
+    m_brushPos = getCenteredCursorPos(pos);
+    invalidate(invalidateRect);
+    return;
+  }
+
+  TPointD centeredPos = getCenteredCursorPos(m_lastPoint);
 
   TToonzImageP ti   = TImageP(getImage(true));
   TPointD rasCenter = ti->getRaster()->getCenterD();
@@ -1426,13 +1490,15 @@ void ToonzRasterBrushTool::leftButtonDrag(const TPointD &pos,
   double thickness  = (m_pressure.getValue())
                          ? computeThickness(e.m_pressure, m_rasThickness) * 2
                          : maxThickness;
-  TRectD invalidateRect;
+
   if (m_isMyPaintStyleSelected) {
     TRasterP ras = ti->getRaster();
     TPointD point(centeredPos + rasCenter);
     double pressure =
         m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
 
+    if (m_maxPressure < pressure) m_maxPressure = pressure;
+
     m_strokeSegmentRect.empty();
     m_toonz_brush->strokeTo(point, pressure, restartBrushTimer());
     TRect updateRect = m_strokeSegmentRect * ras->getBounds();
@@ -1555,8 +1621,14 @@ void ToonzRasterBrushTool::leftButtonUp(const TPointD &pos,
   if (!isValid) {
     return;
   }
-  TPointD centeredPos = getCenteredCursorPos(pos);
+  TPointD centeredPos;
+  if (m_isStraight)
+    centeredPos = getCenteredCursorPos(m_lastPoint);
+  else
+    centeredPos = getCenteredCursorPos(pos);
   double pressure = m_pressure.getValue() && e.isTablet() ? e.m_pressure : 0.5;
+  if (m_isStraight && m_isMyPaintStyleSelected && m_maxPressure > 0.0)
+    pressure = m_maxPressure;
   finishRasterBrush(centeredPos, pressure);
   int tc = ToonzCheck::instance()->getChecks();
   if (tc & ToonzCheck::eGap || tc & ToonzCheck::eAutoclose) invalidate();
@@ -1630,10 +1702,12 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
     /*-- Pencilモードでなく、Hardness=100 の場合のブラシサイズを1段階下げる --*/
     if (!m_pencil.getValue()) thickness -= 1.0;
 
+    if (m_isStraight)
+      thickness = m_rasterTrack->getPointsSequence().at(0).thick;
     TRectD invalidateRect;
     TThickPoint thickPoint(pos + rasCenter, thickness);
     std::vector<TThickPoint> pts;
-    if (m_smooth.getValue() == 0) {
+    if (m_smooth.getValue() == 0 || m_isStraight) {
       pts.push_back(thickPoint);
     } else {
       m_smoothStroke.addPoint(thickPoint);
@@ -1643,13 +1717,17 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
     for (size_t i = 0; i < pts.size(); ++i) {
       const TThickPoint &thickPoint = pts[i];
       m_rasterTrack->add(thickPoint);
-      m_tileSaver->save(m_rasterTrack->getLastRect());
-      m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue(), true);
+      m_tileSaver->save(m_rasterTrack->getLastRect(m_isStraight));
+      m_rasterTrack->generateLastPieceOfStroke(m_pencil.getValue(), true,
+                                               m_isStraight);
 
       std::vector<TThickPoint> brushPoints = m_rasterTrack->getPointsSequence();
       int m                                = (int)brushPoints.size();
       std::vector<TThickPoint> points;
-      if (m == 3) {
+      if (m_isStraight) {
+        points.push_back(brushPoints[0]);
+        points.push_back(brushPoints[2]);
+      } else if (m == 3) {
         points.push_back(brushPoints[0]);
         points.push_back(brushPoints[1]);
       } else {
@@ -1668,7 +1746,7 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
           m_rasterTrack->getStyleId(), m_rasterTrack->isSelective(),
           simLevel.getPointer(), frameId, m_pencil.getValue(), m_isFrameCreated,
           m_isLevelCreated, m_rasterTrack->isPaletteOrder(),
-          m_rasterTrack->isAlphaLocked()));
+          m_rasterTrack->isAlphaLocked(), m_isStraight));
     }
     delete m_rasterTrack;
     m_rasterTrack = 0;
@@ -1677,11 +1755,12 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
     double thickness    = (m_pressure.getValue())
                            ? computeThickness(pressureVal, m_rasThickness)
                            : maxThickness;
+    if (m_isStraight) thickness = m_points[0].thick;
     TPointD rasCenter = ti->getRaster()->getCenterD();
     TRectD invalidateRect;
     TThickPoint thickPoint(pos + rasCenter, thickness);
     std::vector<TThickPoint> pts;
-    if (m_smooth.getValue() == 0) {
+    if (m_smooth.getValue() == 0 || m_isStraight) {
       pts.push_back(thickPoint);
     } else {
       m_smoothStroke.addPoint(thickPoint);
@@ -1691,6 +1770,7 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
     // we need to skip the for-loop here if pts.size() == 0 or else
     // (pts.size() - 1) becomes ULLONG_MAX since size_t is unsigned
     if (pts.size() > 0) {
+      // this doesn't get run for a straight line
       for (size_t i = 0; i < pts.size() - 1; ++i) {
         TThickPoint old = m_points.back();
 
@@ -1731,13 +1811,26 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
                                      m_modifierLockAlpha.getValue());
         m_strokeRect += bbox;
       }
-      TThickPoint point = pts.back();
-      m_points.push_back(point);
+      if (!m_isStraight && m_points.size() > 1) {
+        TThickPoint point = pts.back();
+        m_points.push_back(point);
+      }
       int m = m_points.size();
       std::vector<TThickPoint> points;
-      points.push_back(m_points[m - 3]);
-      points.push_back(m_points[m - 2]);
-      points.push_back(m_points[m - 1]);
+      if (!m_isStraight && m_points.size() > 1) {
+        points.push_back(m_points[m - 3]);
+        points.push_back(m_points[m - 2]);
+        points.push_back(m_points[m - 1]);
+      } else {
+        const TThickPoint point = m_points[0];
+        TThickPoint mid((thickPoint + point) * 0.5,
+                        (point.thick + thickPoint.thick) * 0.5);
+        m_points.push_back(mid);
+        m_points.push_back(thickPoint);
+        points.push_back(m_points[0]);
+        points.push_back(m_points[1]);
+        points.push_back(m_points[2]);
+      }
       TRect bbox = m_bluredBrush->getBoundFromPoints(points);
       updateWorkAndBackupRasters(bbox);
       m_tileSaver->save(bbox);
@@ -1762,13 +1855,16 @@ void ToonzRasterBrushTool::finishRasterBrush(const TPointD &pos,
           m_tileSet, m_points, m_styleId, (DrawOrder)m_drawOrder.getIndex(),
           m_modifierLockAlpha.getValue(), simLevel.getPointer(), frameId,
           m_rasThickness.getValue().second, m_hardness.getValue() * 0.01,
-          m_isFrameCreated, m_isLevelCreated));
+          m_isFrameCreated, m_isLevelCreated, m_isStraight));
     }
   }
   delete m_tileSaver;
 
   m_tileSaver = 0;
 
+  if (m_isStraight) invalidate();  // Clean messy red segment line
+  m_isStraight = false;
+
   /*-- FIdを指定して、描画中にフレームが動いても、
     描画開始時のFidのサムネイルが更新されるようにする。--*/
   notifyImageChanged(frameId);
@@ -1867,6 +1963,11 @@ void ToonzRasterBrushTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
 //-------------------------------------------------------------------------------------------------------------
 
 void ToonzRasterBrushTool::draw() {
+  if (m_isStraight) {
+    tglDrawSegment(m_firstPoint, m_lastPoint);
+    invalidate(TRectD(m_firstPoint, m_lastPoint).enlarge(2));
+  }
+
   /*--ショートカットでのツール切り替え時に赤点が描かれるのを防止する--*/
   if (m_minThick == 0 && m_maxThick == 0 &&
       !Preferences::instance()->getShow0ThickLines())
diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.h b/toonz/sources/tnztools/toonzrasterbrushtool.h
index eeaf0b2..3bf070c 100644
--- a/toonz/sources/tnztools/toonzrasterbrushtool.h
+++ b/toonz/sources/tnztools/toonzrasterbrushtool.h
@@ -229,6 +229,11 @@ protected:
 
   bool m_propertyUpdating = false;
 
+  bool m_isStraight = false;
+  TPointD m_firstPoint;
+  TPointD m_lastPoint;
+  double m_maxPressure = -1.0;
+
 protected:
   static void drawLine(const TPointD &point, const TPointD &centre,
                        bool horizontal, bool isDecimal);
diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
index a13c79c..6d66fff 100644
--- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
@@ -710,6 +710,13 @@ void ToonzVectorBrushTool::leftButtonDown(const TPointD &pos,
     m_currentColor = TPixel32::Red;
     m_active       = true;
   }
+
+  TXshLevel *level = app->getCurrentLevel()->getLevel();
+  if (level == NULL && !m_isPath) {
+    m_active = false;
+    return;
+  }
+
   // assert(0<=m_styleId && m_styleId<2);
   m_track.clear();
   double thickness = (m_pressure.getValue() || m_isPath)
@@ -779,7 +786,39 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
     invalidateRect +=
         TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick);
 
-  if (e.isShiftPressed()) {
+  if (e.isCtrlPressed()) {
+    TPointD m_firstPoint = m_track.getFirstPoint();
+
+    double denominator = m_lastSnapPoint.x - m_firstPoint.x;
+    if (denominator == 0) denominator == 0.001;
+    double slope = ((m_brushPos.y - m_firstPoint.y) / denominator);
+    double angle = std::atan(slope) * (180 / 3.14159);
+    if (abs(angle) > 67.5)
+      m_lastSnapPoint.x = m_firstPoint.x;
+    else if (abs(angle) < 22.5)
+      m_lastSnapPoint.y = m_firstPoint.y;
+    else {
+      double xDistance = m_lastSnapPoint.x - m_firstPoint.x;
+      double yDistance = m_lastSnapPoint.y - m_firstPoint.y;
+      if (abs(xDistance) > abs(yDistance)) {
+        if (abs(yDistance) == yDistance)
+          m_lastSnapPoint.y = m_firstPoint.y + abs(xDistance);
+        else
+          m_lastSnapPoint.y = m_firstPoint.y - abs(xDistance);
+      } else {
+        if (abs(xDistance) == xDistance)
+          m_lastSnapPoint.x = m_firstPoint.x + abs(yDistance);
+        else
+          m_lastSnapPoint.x = m_firstPoint.x - abs(yDistance);
+      }
+    }
+
+    m_smoothStroke.clearPoints();
+    m_track.add(TThickPoint(m_lastSnapPoint, thickness),
+                getPixelSize() * getPixelSize());
+    m_track.removeMiddlePoints();
+    invalidateRect += m_track.getModifiedRegion();
+  } else if (e.isShiftPressed()) {
     m_smoothStroke.clearPoints();
     m_track.add(TThickPoint(m_brushPos, thickness),
                 getPixelSize() * getPixelSize());
diff --git a/toonz/sources/toonzlib/rasterstrokegenerator.cpp b/toonz/sources/toonzlib/rasterstrokegenerator.cpp
index 393d5df..c92106c 100644
--- a/toonz/sources/toonzlib/rasterstrokegenerator.cpp
+++ b/toonz/sources/toonzlib/rasterstrokegenerator.cpp
@@ -45,7 +45,8 @@ void RasterStrokeGenerator::add(const TThickPoint &p) {
 //-----------------------------------------------------------
 
 // Disegna il tratto interamente
-void RasterStrokeGenerator::generateStroke(bool isPencil) const {
+void RasterStrokeGenerator::generateStroke(bool isPencil,
+                                           bool isStraight) const {
   std::vector<TThickPoint> points(m_points);
   int size = points.size();
   // Prende un buffer trasparente di appoggio
@@ -63,8 +64,13 @@ void RasterStrokeGenerator::generateStroke(bool isPencil) const {
     placeOver(m_raster, rasBuffer, newOrigin);
   } else if (size <= 3) {
     std::vector<TThickPoint> partialPoints;
-    partialPoints.push_back(points[0]);
-    partialPoints.push_back(points[1]);
+    if (isStraight && size == 3) {
+      partialPoints.push_back(points[0]);
+      partialPoints.push_back(points[2]);
+    } else {
+      partialPoints.push_back(points[0]);
+      partialPoints.push_back(points[1]);
+    }
     rasterBrush(rasBuffer, partialPoints, m_styleId, !isPencil);
     placeOver(m_raster, rasBuffer, newOrigin);
   } else if (size % 2 == 1) /*-- 奇数の場合 --*/
@@ -106,11 +112,15 @@ void RasterStrokeGenerator::generateStroke(bool isPencil) const {
 //-----------------------------------------------------------
 
 TRect RasterStrokeGenerator::generateLastPieceOfStroke(bool isPencil,
-                                                       bool closeStroke) {
+                                                       bool closeStroke,
+                                                       bool isStraight) {
   std::vector<TThickPoint> points;
   int size = m_points.size();
 
-  if (size == 3) {
+  if (isStraight) {
+    points.push_back(m_points[0]);
+    points.push_back(m_points[2]);
+  } else if (size == 3) {
     points.push_back(m_points[0]);
     points.push_back(m_points[1]);
   } else if (size == 1)
@@ -332,11 +342,14 @@ void RasterStrokeGenerator::placeOver(const TRasterCM32P &out,
 
 //-----------------------------------------------------------
 
-TRect RasterStrokeGenerator::getLastRect() const {
+TRect RasterStrokeGenerator::getLastRect(bool isStraight) const {
   std::vector<TThickPoint> points;
   int size = m_points.size();
 
-  if (size == 3) {
+  if (isStraight) {
+    points.push_back(m_points[0]);
+    points.push_back(m_points[2]);
+  } else if (size == 3) {
     points.push_back(m_points[0]);
     points.push_back(m_points[1]);
   } else if (size == 1)