diff --git a/toonz/sources/include/tools/inputmanager.h b/toonz/sources/include/tools/inputmanager.h
index 7d9a58d..323dba1 100644
--- a/toonz/sources/include/tools/inputmanager.h
+++ b/toonz/sources/include/tools/inputmanager.h
@@ -47,104 +47,6 @@ typedef TSmartPointerT<TInputModifier> TInputModifierP;
 
 
 //*****************************************************************************************
-//    TInputSavePoint definition
-//*****************************************************************************************
-
-class DVAPI TInputSavePoint {
-public:
-  class DVAPI Holder {
-  private:
-    TInputSavePoint *m_savePoint;
-    bool m_lock = false;
-
-  public:
-    inline explicit Holder(TInputSavePoint *savePoint = NULL, bool lock = true):
-      m_savePoint(), m_lock()
-      { set(savePoint, lock); }
-    inline Holder(const Holder &other):
-      m_savePoint(), m_lock()
-      { *this = other; }
-    inline ~Holder()
-      { reset(); }
-
-    inline Holder& operator= (const Holder &other)
-      { set(other.m_savePoint, other.m_lock); return *this; }
-
-    inline operator bool () const
-      { return assigned(); }
-
-    inline void set(TInputSavePoint *savePoint, bool lock) {
-      if (m_savePoint != savePoint) {
-        if (m_savePoint) {
-          if (m_lock) m_savePoint->unlock();
-          m_savePoint->release();
-        }
-        m_savePoint = savePoint;
-        m_lock = lock;
-        if (m_savePoint) {
-          m_savePoint->hold();
-          if (m_lock) savePoint->lock();
-        }
-      } else
-      if (m_lock != lock) {
-        if (m_savePoint) {
-          if (lock) m_savePoint->lock();
-               else m_savePoint->unlock();
-        }
-        m_lock = lock;
-      }
-    }
-
-    inline void reset()
-      { set(NULL, false); }
-    inline void setLock(bool lock)
-      { set(m_savePoint, lock); }
-    inline void lock()
-      { setLock(true); }
-    inline void unlock()
-      { setLock(false); }
-
-    inline TInputSavePoint* savePoint() const
-      { return m_savePoint; }
-    inline bool assigned() const
-      { return savePoint(); }
-    inline bool locked() const
-      { return m_savePoint && m_lock; }
-    inline bool available() const
-      { return m_savePoint && m_savePoint->available; }
-    inline bool isFree() const
-      { return !m_savePoint || m_savePoint->isFree(); }
-  };
-
-  typedef std::vector<Holder> List;
-
-private:
-  int m_refCount;
-  int m_lockCount;
-
-  inline void hold()
-    { ++m_refCount; }
-  inline void release()
-    { if ((--m_refCount) <= 0) delete this; }
-  inline void lock()
-    { ++m_lockCount; }
-  inline void unlock()
-    { --m_lockCount; }
-
-public:
-  bool available;
-
-  inline explicit TInputSavePoint(bool available = false):
-    m_refCount(), m_lockCount(), available(available) { }
-  inline bool isFree() const
-    { return m_lockCount <= 0; }
-
-  static inline Holder create(bool available = false)
-    { return Holder(new TInputSavePoint(available)); }
-};
-
-
-//*****************************************************************************************
 //    TInputModifier definition
 //*****************************************************************************************
 
@@ -164,11 +66,9 @@ public:
 
   virtual void modifyTrack(
     const TTrack &track,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks );
   virtual void modifyTracks(
     const TTrackList &tracks,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks );
 
   virtual void modifyHover(
@@ -221,30 +121,11 @@ public:
   
   virtual void inputHoverEvent(const TInputManager &manager);
 
-  /*! paint single track-point at the top painting level */
-  virtual void inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack);
-
-  /*! create new painting level and return true, or do nothing and return false
-      was:            ------O-------O------
-      become:         ------O-------O------O */
-  virtual bool inputPaintPush() { return false; }
-  /*! paint several track-points at the top painting level
-      was:            ------O-------O------
-      become:         ------O-------O------------ */
+  virtual void inputPaintTracksBegin() { }
+  virtual void inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack, bool preview);
+  virtual void inputPaintTracksEnd() { }
   virtual void inputPaintTracks(const TTrackList &tracks);
-  /*! try to merge N top painting levels and return count of levels that actually merged
-      was:            ------O-------O------O------
-      become (N = 2): ------O--------------------- */
-  virtual int inputPaintApply(int count) { return 0; }
-  /*! reset top level to initial state
-      was:            ------O-------O------O------
-      become:         ------O-------O------O */
-  virtual void inputPaintCancel() { }
-  /*! cancel and pop N painting levels
-      was:            ------O-------O------O------
-      become (N = 2): ------O------- */
-  virtual void inputPaintPop(int count) { }
-  
+
   virtual void inputInvalidateRect(const TRectD &bounds) { }
   
   virtual TTool* inputGetTool() { return nullptr; };
@@ -256,26 +137,15 @@ public:
 //*****************************************************************************************
 
 class DVAPI TInputManager {
-public:
-  class TrackHandler: public TTrackHandler {
-  public:
-    std::vector<int> saves;
-    TrackHandler(TTrack &original, int keysCount = 0):
-      TTrackHandler(original), saves(keysCount, 0)
-      { }
-  };
-
 private:
   TTimerTicks m_lastTicks;
   TInputHandler *m_handler;
   TInputModifier::List m_modifiers;
   std::vector<TTrackList> m_tracks;
   std::vector<THoverList> m_hovers;
-  TInputSavePoint::List m_savePoints;
   TRectD m_prevBounds;
   TRectD m_nextBounds;
   bool m_started;
-  int m_savePointsSent;
 
   static TInputState::TouchId m_lastTouchId;
 
@@ -294,8 +164,6 @@ private:
     return m_lastTicks = ticks;
   }
   
-  void paintRollbackTo(int saveIndex, TTrackList &subTracks);
-  void paintApply(int count, TTrackList &subTracks);
   void paintTracks();
 
   int trackCompare(
diff --git a/toonz/sources/include/tools/modifiers/modifierassistants.h b/toonz/sources/include/tools/modifiers/modifierassistants.h
index 3dcd35d..0ba8059 100644
--- a/toonz/sources/include/tools/modifiers/modifierassistants.h
+++ b/toonz/sources/include/tools/modifiers/modifierassistants.h
@@ -29,7 +29,6 @@ public:
   class DVAPI Modifier: public TTrackModifier {
   public:
     bool initialized;
-    TInputSavePoint::Holder savePoint;
     TGuidelineList guidelines;
 
     Modifier(TTrackHandler &handler);
@@ -52,7 +51,6 @@ public:
 
   void modifyTrack(
     const TTrack &track,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks ) override;
 
   TRectD calcDrawBounds(const TTrackList &tracks, const THoverList &hovers) override;
diff --git a/toonz/sources/include/tools/modifiers/modifierline.h b/toonz/sources/include/tools/modifiers/modifierline.h
index a6966a2..495f711 100644
--- a/toonz/sources/include/tools/modifiers/modifierline.h
+++ b/toonz/sources/include/tools/modifiers/modifierline.h
@@ -33,14 +33,12 @@ public:
 
     bool fixAngle;
     double maxPressure;
-    TInputSavePoint::Holder savePoint;
-
+    
     TTrackPoint calcPoint(double originalIndex) override;
   };
 
   void modifyTrack(
     const TTrack &track,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks ) override;
 };
 
diff --git a/toonz/sources/include/tools/modifiers/modifiersegmentation.h b/toonz/sources/include/tools/modifiers/modifiersegmentation.h
index af4278c..a979c8b 100644
--- a/toonz/sources/include/tools/modifiers/modifiersegmentation.h
+++ b/toonz/sources/include/tools/modifiers/modifiersegmentation.h
@@ -38,7 +38,6 @@ public:
   
   void modifyTrack(
     const TTrack &track,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks ) override;
 };
 
diff --git a/toonz/sources/include/tools/modifiers/modifiertangents.h b/toonz/sources/include/tools/modifiers/modifiertangents.h
index 8ead779..a7e6232 100644
--- a/toonz/sources/include/tools/modifiers/modifiertangents.h
+++ b/toonz/sources/include/tools/modifiers/modifiertangents.h
@@ -31,17 +31,15 @@ public:
     explicit Modifier(TTrackHandler &handler):
       TTrackModifier(handler) { }
 
-    TInputSavePoint::Holder savePoint;
     TTrackTangentList tangents;
 
     TTrackPoint calcPoint(double originalIndex) override;
   };
 
-  TTrackTangent calcLastTangent(const TTrack &track) const;
+  TTrackTangent calcTangent(const TTrack &track, int index) const;
 
   void modifyTrack(
     const TTrack &track,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks ) override;
 };
 
diff --git a/toonz/sources/include/tools/modifiers/modifiertest.h b/toonz/sources/include/tools/modifiers/modifiertest.h
index 91911af..e410547 100644
--- a/toonz/sources/include/tools/modifiers/modifiertest.h
+++ b/toonz/sources/include/tools/modifiers/modifiertest.h
@@ -50,7 +50,6 @@ public:
   TModifierTest(int count, double radius);
 
   void modifyTrack(const TTrack &track,
-                   const TInputSavePoint::Holder &savePoint,
                    TTrackList &outTracks) override;
 };
 
diff --git a/toonz/sources/include/tools/track.h b/toonz/sources/include/tools/track.h
index eb12057..aee3ae5 100644
--- a/toonz/sources/include/tools/track.h
+++ b/toonz/sources/include/tools/track.h
@@ -183,10 +183,12 @@ public:
   mutable TTrackToolHandlerP toolHandler;
   mutable int pointsRemoved;
   mutable int pointsAdded;
+  mutable int fixedPointsAdded;
 
 private:
   TTrackPointList m_points;
   const TTrackPoint m_none;
+  int m_pointsFixed;
 
 public:
 
@@ -208,7 +210,7 @@ public:
   inline TTimerTicks ticks() const
     { return keyHistory.ticks(); }
   inline bool changed() const
-    { return pointsAdded != 0 || pointsRemoved != 0; }
+    { return pointsRemoved || pointsAdded || fixedPointsAdded; }
 
   const TTrack* root() const;
   int level() const;
@@ -236,6 +238,10 @@ public:
 
   inline int size() const
     { return (int)m_points.size(); }
+  inline int fixedSize() const
+    { return m_pointsFixed; }
+  inline int previewSize() const
+    { return size() - fixedSize(); }
   inline bool empty() const
     { return m_points.empty(); }
   inline const TTrackPoint& front() const
@@ -244,6 +250,8 @@ public:
     { return point(size() - 1); }
   inline bool finished() const
     { return !m_points.empty() && back().final; }
+  inline bool fixedFinished() const
+    { return finished() && !previewSize(); }
   inline const TTrackPoint& operator[] (int index) const
     { return point(index); }
   inline const TTrackPointList& points() const
@@ -253,14 +261,21 @@ public:
     { pointsRemoved = 0; }
   inline void resetAdded() const
     { pointsAdded = 0; }
+  inline void resetFixedAdded() const
+    { fixedPointsAdded = 0; }
   inline void resetChanges() const
-    { resetRemoved(); resetAdded(); }
+    { resetRemoved(); resetAdded(); resetFixedAdded(); }
 
-  void push_back(const TTrackPoint &point);
+  void push_back(const TTrackPoint &point, bool fixed);
   void pop_back(int count = 1);
+  void fix_points(int count = 1);
 
   inline void truncate(int count)
     { pop_back(size() - count); }
+  inline void fix_to(int count)
+    { fix_points(count - fixedSize()); }
+  inline void fix_all()
+    { fix_to(size()); }
 
   inline const TTrackPoint& current() const
     { return point(size() - pointsAdded); }
diff --git a/toonz/sources/tnztools/assistant.cpp b/toonz/sources/tnztools/assistant.cpp
index 5e0ec9c..2807468 100644
--- a/toonz/sources/tnztools/assistant.cpp
+++ b/toonz/sources/tnztools/assistant.cpp
@@ -85,7 +85,7 @@ TGuideline::calcTrackWeight(const TTrack &track, const TAffine &toScreen, bool &
     prev = p;
 
     if (sumLength >= maxLength)
-      { outLongEnough = true; break; }
+      { outLongEnough = i < track.fixedSize(); break; }
   }
   return sumWeight > TConsts::epsilon
        ? sumDeviation/sumWeight
diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp
index cdc7a4c..8b4b7d2 100644
--- a/toonz/sources/tnztools/fullcolorbrushtool.cpp
+++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp
@@ -312,11 +312,11 @@ bool FullColorBrushTool::preLeftButtonDown() {
   m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer()));
   m_inputmanager.addModifier(
       TInputModifierP(m_modifierAssistants.getPointer()));
-  m_inputmanager.addModifier(
-      TInputModifierP(m_modifierSegmentation.getPointer()));
 #ifndef NDEBUG
   m_inputmanager.addModifier(TInputModifierP(m_modifierTest.getPointer()));
 #endif
+  m_inputmanager.addModifier(
+      TInputModifierP(m_modifierSegmentation.getPointer()));
 
   touchImage();
 
@@ -505,9 +505,13 @@ void FullColorBrushTool::inputSetBusy(bool busy) {
 
 void FullColorBrushTool::inputPaintTrackPoint(const TTrackPoint &point,
                                               const TTrack &track,
-                                              bool firstTrack) {
+                                              bool firstTrack,
+                                              bool preview)
+{
   // get raster
-  if (!m_started || !getViewer()) return;
+  if (!m_started || !getViewer() || preview)
+    return;
+  
   TRasterImageP ri = (TRasterImageP)getImage(true);
   if (!ri) return;
   TRasterP ras      = ri->getRaster();
diff --git a/toonz/sources/tnztools/fullcolorbrushtool.h b/toonz/sources/tnztools/fullcolorbrushtool.h
index 239ea92..cdb8450 100644
--- a/toonz/sources/tnztools/fullcolorbrushtool.h
+++ b/toonz/sources/tnztools/fullcolorbrushtool.h
@@ -81,7 +81,7 @@ public:
                       const TInputState &state) override;
   void inputSetBusy(bool busy) override;
   void inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track,
-                            bool firstTrack) override;
+                            bool firstTrack, bool preview) override;
   void inputInvalidateRect(const TRectD &bounds) override;
   TTool *inputGetTool() override { return this; };
 
diff --git a/toonz/sources/tnztools/inputmanager.cpp b/toonz/sources/tnztools/inputmanager.cpp
index bc00bb9..efc0754 100644
--- a/toonz/sources/tnztools/inputmanager.cpp
+++ b/toonz/sources/tnztools/inputmanager.cpp
@@ -29,7 +29,6 @@ TInputModifier::setManager(TInputManager *manager) {
 void
 TInputModifier::modifyTrack(
   const TTrack &track,
-  const TInputSavePoint::Holder &savePoint,
   TTrackList &outTracks )
 {
   if (!track.handler) {
@@ -51,7 +50,8 @@ TInputModifier::modifyTrack(
     TTrack &subTrack = **ti;
     subTrack.truncate(start);
     for(int i = start; i < track.size(); ++i)
-      subTrack.push_back( subTrack.modifier->calcPoint(i) );
+      subTrack.push_back( subTrack.modifier->calcPoint(i), false );
+    subTrack.fix_to(track.fixedSize());
   }
   track.resetChanges();
 }
@@ -60,11 +60,10 @@ TInputModifier::modifyTrack(
 void
 TInputModifier::modifyTracks(
     const TTrackList &tracks,
-    const TInputSavePoint::Holder &savePoint,
     TTrackList &outTracks )
 {
   for(TTrackList::const_iterator i = tracks.begin(); i != tracks.end(); ++i)
-    modifyTrack(**i, savePoint, outTracks);
+    modifyTrack(**i, outTracks);
 }
 
 
@@ -127,9 +126,9 @@ TInputModifier::draw(const TTrackList &tracks, const std::vector<TPointD> &hover
 bool
 TInputHandler::inputKeyEvent(
   bool press,
-  TInputState::Key key,
+  TInputState::Key,
   QKeyEvent *event,
-  const TInputManager &manager )
+  const TInputManager& )
 {
   return press && event && inputKeyDown(event);
 }
@@ -138,7 +137,7 @@ TInputHandler::inputKeyEvent(
 void
 TInputHandler::inputButtonEvent(
   bool press,
-  TInputState::DeviceId device,
+  TInputState::DeviceId,
   TInputState::Button button,
   const TInputManager &manager )
 {
@@ -155,8 +154,8 @@ TInputHandler::inputHoverEvent(const TInputManager &manager) {
 
 
 void
-TInputHandler::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack) {
-  if (firstTrack) {
+TInputHandler::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack, bool preview) {
+  if (firstTrack && !preview) {
     if (track.pointsAdded == track.size())
       inputLeftButtonDown(point, track);
     else
@@ -164,14 +163,25 @@ TInputHandler::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &trac
       inputLeftButtonUp(point, track);
     else
       inputLeftButtonDrag(point, track);
-   }
+  }
 }
 
 
 void
 TInputHandler::inputPaintTracks(const TTrackList &tracks) {
+  // prepare tracks counters
+  for(TTrackList::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
+    (*i)->pointsAdded = (*i)->fixedPointsAdded + (*i)->previewSize();
+    (*i)->resetRemoved();
+  }
+  
+  // begin paint
+  bool preview = false;
+  bool paintStarted = false;
+
   // paint track points in chronological order
   while(true) {
+    // find earlier not painted point
     TTrackP track;
     TTimerTicks minTicks = 0;
     double minTimeOffset = 0.0;
@@ -187,10 +197,27 @@ TInputHandler::inputPaintTracks(const TTrackList &tracks) {
         }
       }
     }
-    if (!track) break;
-    inputPaintTrackPoint(track->current(), *track, track == tracks.front());
+    
+    if (!track)
+      break; // all tracks are painted
+    
+    if (track->pointsAdded <= track->previewSize())
+      preview = true;
+    if (!paintStarted)
+      { inputPaintTracksBegin(); paintStarted = true; }
+    inputPaintTrackPoint(track->current(), *track, track == tracks.front(), preview);
+    
+    // update counters
     --track->pointsAdded;
+    if (!preview) {
+      assert(track->fixedPointsAdded > 0);
+      --track->fixedPointsAdded;
+    }
   }
+
+  // end paint
+  if (paintStarted)
+    inputPaintTracksEnd();
 }
 
 
@@ -205,162 +232,53 @@ TInputManager::TInputManager():
   m_tracks(1),
   m_hovers(1),
   m_started(),
-  m_savePointsSent(),
   drawPreview()
 { }
 
 
 void
-TInputManager::paintRollbackTo(int saveIndex, TTrackList &subTracks) {
-  if (saveIndex >= (int)m_savePoints.size())
-    return;
-
-  int level = saveIndex + 1;
-  if (level <= m_savePointsSent) {
-    if (m_handler) {
-      if (level < m_savePointsSent)
-        m_handler->inputPaintPop(m_savePointsSent - level);
-      m_handler->inputPaintCancel();
-    }
-    m_savePointsSent = level;
-  }
-
-  for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i) {
-    TTrack &track = **i;
-    if (TrackHandler *handler = dynamic_cast<TrackHandler*>(track.handler.getPointer())) {
-      handler->saves.resize(level);
-      int cnt = handler->saves[saveIndex];
-      track.resetRemoved();
-      track.pointsAdded = track.size() - cnt;
-    }
-  }
-  for(int i = level; i < (int)m_savePoints.size(); ++i)
-    m_savePoints[i].savePoint()->available = false;
-  m_savePoints.resize(level);
-}
-
-
-void
-TInputManager::paintApply(int count, TTrackList &subTracks) {
-  if (count <= 0)
-    return;
-
-  int level = (int)m_savePoints.size() - count;
-  bool resend = true;
-
-  if (level < m_savePointsSent) {
-    // apply
-    int applied = m_handler ? m_handler->inputPaintApply(m_savePointsSent - level) : false;
-    applied = std::max(0, std::min(m_savePointsSent - level, applied));
-    m_savePointsSent -= applied;
-    if (m_savePointsSent == level) resend = false;
-  }
-
-  if (level < m_savePointsSent) {
-    // rollback
-    if (m_handler) m_handler->inputPaintPop(m_savePointsSent - level);
-    m_savePointsSent = level;
+TInputManager::paintTracks() {
+  // run modifiers
+  for(int i = 0; i < (int)m_modifiers.size(); ++i) {
+    m_tracks[i+1].clear();
+    m_modifiers[i]->modifyTracks(m_tracks[i], m_tracks[i+1]);
   }
+  TTrackList &subTracks = m_tracks.back();
 
-  // remove keypoints
-  for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i) {
-    TTrack &track = **i;
-    if (TrackHandler *handler = dynamic_cast<TrackHandler*>(track.handler.getPointer())) {
-      if (resend) {
-        track.resetRemoved();
-        track.pointsAdded = track.size() - handler->saves[m_savePointsSent];
-      }
-      handler->saves.resize(level);
-    }
+  
+  // begin painting if need
+  bool changed = false;
+  for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i)
+    if ((*i)->changed())
+      { changed = true; break; }
+  if (!m_started && changed) {
+    m_started = true;
+    if (m_handler) m_handler->inputSetBusy(true);
   }
-  for(int i = level; i < (int)m_savePoints.size(); ++i)
-    m_savePoints[i].savePoint()->available = false;
-  m_savePoints.resize(level);
-}
 
-
-void
-TInputManager::paintTracks() {
+  
+  // paint tracks
+  if (changed && m_handler)
+    m_handler->inputPaintTracks(subTracks);
+  
+  
+  // end painting if all tracks are finished
   bool allFinished = true;
   for(TTrackList::const_iterator i = m_tracks.front().begin(); i != m_tracks.front().end(); ++i)
-    if (!(*i)->finished())
+    if (!(*i)->fixedFinished())
       { allFinished = false; break; }
-
-  while(true) {
-    // run modifiers
-    TInputSavePoint::Holder newSavePoint = TInputSavePoint::create(true);
-    for(int i = 0; i < (int)m_modifiers.size(); ++i) {
-      m_tracks[i+1].clear();
-      m_modifiers[i]->modifyTracks(m_tracks[i], newSavePoint, m_tracks[i+1]);
-    }
-    TTrackList &subTracks = m_tracks.back();
-
-    // is paint started?
-    if (!m_started && !subTracks.empty()) {
-      m_started = true;
-      if (m_handler) m_handler->inputSetBusy(true);
-    }
-
-    // create handlers
+  if (allFinished)
     for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i)
-      if (!(*i)->handler)
-        (*i)->handler = new TrackHandler(**i, (int)m_savePoints.size());
-
-    if (!m_savePoints.empty()) {
-      // rollback
-      int rollbackIndex = (int)m_savePoints.size();
-      for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i) {
-        TTrack &track = **i;
-        if (track.pointsRemoved > 0) {
-          int count = track.size() - track.pointsAdded;
-          if (TrackHandler *handler = dynamic_cast<TrackHandler*>(track.handler.getPointer()))
-            while(rollbackIndex > 0 && (rollbackIndex >= (int)m_savePoints.size() || handler->saves[rollbackIndex] > count))
-              --rollbackIndex;
-        }
-      }
-      paintRollbackTo(rollbackIndex, subTracks);
-
-      // apply
-      int applyCount = 0;
-      while(applyCount < (int)m_savePoints.size() && m_savePoints[(int)m_savePoints.size() - applyCount - 1].isFree())
-        ++applyCount;
-      paintApply(applyCount, subTracks);
+      if (!(*i)->fixedFinished())
+        { allFinished = false; break; }
+        
+  if (allFinished) {
+    if (m_started) {
+      if (m_handler) m_handler->inputSetBusy(false);
+      m_started = false;
     }
-
-    // send to handler
-    if (m_savePointsSent == (int)m_savePoints.size() && !subTracks.empty() && m_handler)
-      m_handler->inputPaintTracks(subTracks);
-    for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i)
-      (*i)->resetChanges();
-
-    // is paint finished?
-    newSavePoint.unlock();
-    if (newSavePoint.isFree()) {
-      newSavePoint.savePoint()->available = false;
-      if (allFinished) {
-        paintApply((int)m_savePoints.size(), subTracks);
-        // send to tool final
-        if (!subTracks.empty()) {
-          if (m_handler) m_handler->inputPaintTracks(subTracks);
-          for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i)
-            (*i)->resetChanges();
-        }
-        for(std::vector<TTrackList>::iterator i = m_tracks.begin(); i != m_tracks.end(); ++i)
-          i->clear();
-        if (m_started) {
-          if (m_handler) m_handler->inputSetBusy(false);
-          m_started = false;
-        }
-      }
-      break;
-    }
-
-    // create save point
-    if (m_handler && m_handler->inputPaintPush()) ++m_savePointsSent;
-    m_savePoints.push_back(newSavePoint);
-    for(TTrackList::const_iterator i = subTracks.begin(); i != subTracks.end(); ++i)
-      if (TrackHandler *handler = dynamic_cast<TrackHandler*>((*i)->handler.getPointer()))
-        handler->saves.push_back((*i)->size());
+    for(int i = 0; i < (int)m_tracks.size(); ++i)
+      m_tracks[i].clear();
   }
 }
 
@@ -444,14 +362,16 @@ TInputManager::addTrackPoint(
   double time,
   bool final )
 {
-  track->push_back( TTrackPoint(
-    position,
-    pressure,
-    tilt,
-    (double)track->size(),
-    time,
-    0.0, // length will calculated inside of TTrack::push_back
-    final ));
+  track->push_back(
+    TTrackPoint(
+      position,
+      pressure,
+      tilt,
+      (double)track->size(),
+      time,
+      0.0, // length will calculated inside of TTrack::push_back
+      final ),
+    true );
 }
 
 
@@ -502,15 +422,9 @@ TInputManager::finishTracks() {
 
 void
 TInputManager::reset() {
-  // forget about handler paint stack
+  // forget about handler busy state
   // assuime it was already reset by outside
   m_started = false;
-  m_savePointsSent = 0;
-
-  // reset save point
-  for(int i = 0; i < (int)m_savePoints.size(); ++i)
-    m_savePoints[i].savePoint()->available = false;
-  m_savePoints.clear();
 
   // reset tracks
   for(int i = 0; i < (int)m_tracks.size(); ++i)
@@ -660,16 +574,15 @@ TInputManager::calcDrawBounds() {
   for(int i = 0; i < (int)m_modifiers.size(); ++i)
     bounds += m_modifiers[i]->calcDrawBounds(m_tracks[i], m_hovers[i]);
 
-  if (m_savePointsSent < (int)m_savePoints.size()) {
+  if ( debugInputManager || drawPreview ) {
     for(TTrackList::const_iterator ti = getOutputTracks().begin(); ti != getOutputTracks().end(); ++ti) {
       TTrack &track = **ti;
-      if (TrackHandler *handler = dynamic_cast<TrackHandler*>(track.handler.getPointer())) {
-        int start = handler->saves[m_savePointsSent] - 1;
-        if (start < 0) start = 0;
-        if (start + 1 < track.size())
-          for(int i = start + 1; i < track.size(); ++i)
-            bounds += boundingBox(track[i-1].position, track[i].position);
-      }
+      int painted = track.fixedSize() - track.fixedPointsAdded;
+      if (painted < 0) painted = 0;
+      int start = debugInputManager ? 0 : painted;
+      if (start + 1 < track.size())
+        for(int i = start + 1; i < track.size(); ++i)
+          bounds += boundingBox(track[i-1].position, track[i].position);
     }
   }
 
@@ -685,8 +598,8 @@ TInputManager::draw() {
   m_prevBounds = m_nextBounds;
   m_nextBounds = TRectD();
   
-  // paint not sent sub-tracks
-  if ( debugInputManager || (drawPreview && m_savePointsSent < (int)m_savePoints.size()) ) {
+  // paint not fixed parts of tracks
+  if ( debugInputManager || drawPreview ) {
     glPushAttrib(GL_ALL_ATTRIB_BITS);
     tglEnableBlending();
     tglEnableLineSmooth(true, 1.0);
@@ -695,38 +608,35 @@ TInputManager::draw() {
     double colorWhite[4] = { 1.0, 1.0, 1.0, 1.0 };
     for(TTrackList::const_iterator ti = getOutputTracks().begin(); ti != getOutputTracks().end(); ++ti) {
       TTrack &track = **ti;
-      if (TrackHandler *handler = dynamic_cast<TrackHandler*>(track.handler.getPointer())) {
-        int start = debugInputManager ? 0 : handler->saves[m_savePointsSent] - 1;
-        if (start < 0) start = 0;
-        if (start + 1 < track.size()) {
-          //int level = m_savePointsSent;
-          //colorBlack[3] = (colorWhite[3] = 0.8);
-          double radius = 2.0;
-          for(int i = start + 1; i < track.size(); ++i) {
-            //while(level < (int)handler->saves.size() && handler->saves[level] <= i)
-            //  colorBlack[3] = (colorWhite[3] *= 0.8), ++level;
-
-            const TPointD &a = track[i-1].position;
-            const TPointD &b = track[i].position;
-            TPointD d = b - a;
-
-            double k = norm2(d);
-            if (k > TConsts::epsilon*TConsts::epsilon) {
-              k = 0.5*pixelSize/sqrt(k);
-              d = TPointD(-k*d.y, k*d.x);
-              glColor4dv(colorWhite);
-              tglDrawSegment(a - d, b - d);
-              glColor4dv(colorBlack);
-              tglDrawSegment(a + d, b + d);
-              radius = 2.0;
-            } else {
-              radius += 2.0;
-            }
-
-            if (debugInputManager) {
-              glColor4d(0.0, 0.0, 0.0, 0.25);
-              tglDrawCircle(b, radius*pixelSize);
-            }
+      int painted = track.fixedSize() - track.fixedPointsAdded;
+      if (painted < 0) painted = 0;
+      int start = debugInputManager ? 0 : painted;
+      if (start + 1 < track.size()) {
+        double radius = 2.0;
+        for(int i = start + 1; i < track.size(); ++i) {
+          //if (i >= painted)
+          //  colorBlack[3] = colorWhite[3] = 0.8;
+
+          const TPointD &a = track[i-1].position;
+          const TPointD &b = track[i].position;
+          TPointD d = b - a;
+
+          double k = norm2(d);
+          if (k > TConsts::epsilon*TConsts::epsilon) {
+            k = 0.5*pixelSize/sqrt(k);
+            d = TPointD(-k*d.y, k*d.x);
+            glColor4dv(colorWhite);
+            tglDrawSegment(a - d, b - d);
+            glColor4dv(colorBlack);
+            tglDrawSegment(a + d, b + d);
+            radius = 2.0;
+          } else {
+            radius += 2.0;
+          }
+
+          if (debugInputManager) {
+            glColor4d(0.0, 0.0, 0.0, 0.25);
+            tglDrawCircle(b, radius*pixelSize);
           }
         }
       }
diff --git a/toonz/sources/tnztools/modifiers/modifierassistants.cpp b/toonz/sources/tnztools/modifiers/modifierassistants.cpp
index 1a62e44..208bb64 100644
--- a/toonz/sources/tnztools/modifiers/modifierassistants.cpp
+++ b/toonz/sources/tnztools/modifiers/modifierassistants.cpp
@@ -113,64 +113,68 @@ TModifierAssistants::scanAssistants(
 void
 TModifierAssistants::modifyTrack(
   const TTrack &track,
-  const TInputSavePoint::Holder &savePoint,
   TTrackList &outTracks )
 {
   if (!track.handler) {
     track.handler = new TTrackHandler(track);
     Modifier *modifier = new Modifier(*track.handler);
-    if (!drawOnly)
-      scanAssistants(&track[0].position, 1, &modifier->guidelines, false, true);
-
     track.handler->tracks.push_back(new TTrack(modifier));
-
-    if ((int)modifier->guidelines.size() > 1) {
-      modifier->savePoint = savePoint;
-      outTracks.push_back(track.handler->tracks.front());
-      return;
-    }
   }
 
   outTracks.push_back(track.handler->tracks.front());
   TTrack &subTrack = *track.handler->tracks.front();
-  if (!track.changed()) return;
-  if (Modifier *modifier = dynamic_cast<Modifier*>(subTrack.modifier.getPointer())) {
-    // remove points
-    int start = track.size() - track.pointsAdded;
-    if (start < 0) start = 0;
-
-    if ((int)modifier->guidelines.size() > 1 && modifier->savePoint.available()) {
-      // select guideline
-      bool longEnough = false;
-      if (TInputManager *manager = getManager())
-      if (TInputHandler *handler = manager->getHandler())
-      if (TTool *tool = handler->inputGetTool())
-      if (TToolViewer *viewer = tool->getViewer()) {
-        TAffine trackToScreen = tool->getMatrix();
-        if (tool->getToolType() & TTool::LevelTool)
-          if (TObjectHandle *objHandle = TTool::getApplication()->getCurrentObject())
-            if (!objHandle->isSpline())
-              trackToScreen *= TScale(viewer->getDpiScale().x, viewer->getDpiScale().y);
-        trackToScreen *= viewer->get3dViewMatrix().get2d().inv();
-        TGuidelineP guideline = TGuideline::findBest(modifier->guidelines, track, trackToScreen, longEnough);
-        if (guideline != modifier->guidelines.front())
-          for(int i = 1; i < (int)modifier->guidelines.size(); ++i)
-            if (modifier->guidelines[i] == guideline) {
-              std::swap(modifier->guidelines[i], modifier->guidelines.front());
-              start = 0;
-              break;
-            }
-      }
-      modifier->savePoint.setLock(!longEnough);
-    } else {
-      modifier->savePoint.reset();
-    }
+  if (!track.changed())
+    return;
+  Modifier *modifier = dynamic_cast<Modifier*>(subTrack.modifier.getPointer());
+  if (!modifier)
+    return;
+    
+  // remove points
+  int start = track.size() - track.pointsAdded;
+  if (start < 0) start = 0;
+
+  if (!drawOnly && start <= 0) {
+    modifier->guidelines.clear();
+    scanAssistants(&track[0].position, 1, &modifier->guidelines, false, true);
+  }
+  
+  bool fixed = subTrack.fixedSize() || modifier->guidelines.size() <= 1;
 
-    // add points
-    subTrack.truncate(start);
-    for(int i = start; i < track.size(); ++i)
-      subTrack.push_back( modifier->calcPoint(i) );
+  // select guideline
+  if (!fixed)
+  if (TInputManager *manager = getManager())
+  if (TInputHandler *handler = manager->getHandler())
+  if (TTool *tool = handler->inputGetTool())
+  if (TToolViewer *viewer = tool->getViewer()) {
+    TAffine trackToScreen = tool->getMatrix();
+    if (tool->getToolType() & TTool::LevelTool)
+      if (TObjectHandle *objHandle = TTool::getApplication()->getCurrentObject())
+        if (!objHandle->isSpline())
+          trackToScreen *= TScale(viewer->getDpiScale().x, viewer->getDpiScale().y);
+    trackToScreen *= viewer->get3dViewMatrix().get2d().inv();
+    TGuidelineP guideline = TGuideline::findBest(modifier->guidelines, track, trackToScreen, fixed);
+    if (guideline != modifier->guidelines.front())
+      for(int i = 1; i < (int)modifier->guidelines.size(); ++i)
+        if (modifier->guidelines[i] == guideline) {
+          std::swap(modifier->guidelines[i], modifier->guidelines.front());
+          start = 0;
+          break;
+        }
   }
+
+  // add points
+  subTrack.truncate(start);
+  for(int i = start; i < track.size(); ++i)
+    subTrack.push_back( modifier->calcPoint(i), false );
+  
+  // fix points
+  if (fixed) {
+    subTrack.fix_to(track.fixedSize());
+  } else
+  if (track.fixedSize()) {
+    subTrack.fix_to(1);
+  }
+
   track.resetChanges();
 }
 
diff --git a/toonz/sources/tnztools/modifiers/modifierline.cpp b/toonz/sources/tnztools/modifiers/modifierline.cpp
index ed923ce..e678914 100644
--- a/toonz/sources/tnztools/modifiers/modifierline.cpp
+++ b/toonz/sources/tnztools/modifiers/modifierline.cpp
@@ -31,12 +31,10 @@ TTrackPoint TModifierLine::Modifier::calcPoint(double originalIndex) {
 }
 
 void TModifierLine::modifyTrack(const TTrack &track,
-                                const TInputSavePoint::Holder &savePoint,
                                 TTrackList &outTracks) {
   if (!track.handler) {
     track.handler       = new TTrackHandler(track);
     Modifier *modifier  = new Modifier(*track.handler);
-    modifier->savePoint = savePoint;
     track.handler->tracks.push_back(new TTrack(modifier));
   }
 
@@ -66,7 +64,6 @@ void TModifierLine::modifyTrack(const TTrack &track,
   }
   modifier->maxPressure = maxPressure;
   modifier->fixAngle    = fixAngle;
-  if (track.finished()) modifier->savePoint.reset();
 
   subTrack.truncate(0);
 
@@ -75,7 +72,7 @@ void TModifierLine::modifyTrack(const TTrack &track,
     p.originalIndex = 0;
     p.pressure      = maxPressure;
     p.tilt          = TPointD();
-    subTrack.push_back(p);
+    subTrack.push_back(p, false);
   }
 
   if (track.size() > 1) {
@@ -84,8 +81,11 @@ void TModifierLine::modifyTrack(const TTrack &track,
     p.pressure      = maxPressure;
     p.tilt          = TPointD();
     if (fixAngle) calcFixedAngle(subTrack.front(), p);
-    subTrack.push_back(p);
+    subTrack.push_back(p, false);
   }
 
+  if (track.fixedFinished())
+    subTrack.fix_all();
+
   track.resetChanges();
 }
diff --git a/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp b/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp
index 447c9e4..1fdf154 100644
--- a/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiersegmentation.cpp
@@ -31,7 +31,7 @@ TModifierSegmentation::addSegments(
   TPointD d = p1.position - p0.position;
 
   if (level >= maxRecursion || (fabs(d.x) <= m_step.x && fabs(d.y) <= m_step.y)) {
-    track.push_back(p1);
+    track.push_back(p1, false);
     return;
   }
 
@@ -44,7 +44,6 @@ TModifierSegmentation::addSegments(
 void
 TModifierSegmentation::modifyTrack(
   const TTrack &track,
-  const TInputSavePoint::Holder &savePoint,
   TTrackList &outTracks )
 {
   if (!track.handler) {
@@ -77,5 +76,10 @@ TModifierSegmentation::modifyTrack(
     p0 = p1;
   }
 
+  // fix points
+  if (track.fixedSize())
+    subTrack.fix_to(
+      subTrack.floorIndex(subTrack.indexByOriginalIndex(track.fixedSize() - 1)) + 1 );
+  
   track.resetChanges();
 }
diff --git a/toonz/sources/tnztools/modifiers/modifiertangents.cpp b/toonz/sources/tnztools/modifiers/modifiertangents.cpp
index f71c56e..531778c 100644
--- a/toonz/sources/tnztools/modifiers/modifiertangents.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiertangents.cpp
@@ -22,11 +22,20 @@ TModifierTangents::Modifier::calcPoint(double originalIndex) {
     const TTrackPoint &p1 = original[i1];
     TTrackTangent t0 = i0 < (int)tangents.size() ? tangents[i0] : TTrackTangent();
     TTrackTangent t1 = i1 < (int)tangents.size() ? tangents[i1] : TTrackTangent();
-    double l = fabs(p1.length - p0.length);
+    double l = p1.length - p0.length;
+    
     t0.position.x *= l;
     t0.position.y *= l;
+    t0.pressure *= l;
+    t0.tilt.x *= l;
+    t0.tilt.y *= l;
+    
     t1.position.x *= l;
     t1.position.y *= l;
+    t1.pressure *= l;
+    t1.tilt.x *= l;
+    t1.tilt.y *= l;
+    
     p = TTrack::interpolationSpline(p0, p1, t0, t1, frac);
   }
   p.originalIndex = originalIndex;
@@ -40,25 +49,33 @@ TModifierTangents::Modifier::calcPoint(double originalIndex) {
 
 
 TTrackTangent
-TModifierTangents::calcLastTangent(const TTrack &track) const {
+TModifierTangents::calcTangent(const TTrack &track, int index) const {
   if (track.size() < 2) return TTrackTangent();
-  const TTrackPoint &p0 = track[track.size() - 2];
-  const TTrackPoint &p1 = track.back();
-
-  // calculate tangent (with normalized position)
-  // with valid points time normalization does not required
-  double dl = p1.length - p0.length;
+  const TTrackPoint &p0 = track[index-1];
+  const TTrackPoint &p1 = track[index];
+  const TTrackPoint &p2 = track[index+1];
+
+  // calculate tangent length by time
+  // for that we need know time of actual user input
+  // instead of time when message dispatched
+  //double dt = p2.time - p0.time;
+  //double k = dt > TConsts::epsilon ? (p1.time - p0.time)/dt : 0.0;
+  ////if (&p0 == &p1 || &p1 == &p2) k *= 2.0;
+  
+  // calculate tangent without time (based on length)
+  double k = p2.length - p0.length;
+  k = k > TConsts::epsilon ? 1/k : 0;
+  
   return TTrackTangent(
-    dl > TConsts::epsilon ? (p1.position - p0.position)*(1.0/dl) : TPointD(),
-    p1.pressure - p0.pressure,
-    p1.tilt - p0.tilt );
+    (p2.position - p0.position)*k,
+    (p2.pressure - p0.pressure)*k,
+    (p2.tilt - p0.tilt)*k );
 }
 
 
 void
 TModifierTangents::modifyTrack(
   const TTrack &track,
-  const TInputSavePoint::Holder &savePoint,
   TTrackList &outTracks )
 {
   if (!track.handler) {
@@ -77,83 +94,31 @@ TModifierTangents::modifyTrack(
     return;
 
   outTracks.push_back(track.handler->tracks.front());
-
-  if ( !track.changed()
-    && track.size() == subTrack.size()
-    && track.size() == (int)modifier->tangents.size() )
-      return;
-
-  if (!track.changed() && subTrack.size() == track.size() - 1) {
-    // add temporary point
-    modifier->tangents.push_back(calcLastTangent(track));
-    subTrack.push_back(track.back());
-  } else {
-    // apply permanent changes
-
-    // remove points
-    int start = track.size() - track.pointsAdded;
-    if (start < 0) start = 0;
-    if (start > 1) --start;
-    subTrack.truncate(start);
-    TTrackTangent lastTangent =
-        start < (int)modifier->tangents.size() ? modifier->tangents[start]
-      : modifier->tangents.empty() ? TTrackTangent()
-      : modifier->tangents.back();
-    modifier->tangents.resize(start, lastTangent);
-
-    // add first point
-    int index = start;
-    if (index == 0) {
-      modifier->tangents.push_back(TTrackTangent());
-      subTrack.push_back(track.back());
-      ++index;
-    }
-
-    // add points with tangents
-    if (track.size() > 2) {
-      while(index < track.size() - 1) {
-        const TTrackPoint &p0 = track[index-1];
-        const TTrackPoint &p1 = track[index];
-        const TTrackPoint &p2 = track[index+1];
-
-        // calculate tangents length by time
-        // for that we need read time of user input
-        // instead of time when message dispatched
-        //double dt = p2.time - p0.time;
-        //double k = dt > TConsts::epsilon ? (p1.time - p0.time)/dt : 0.0;
-        //TTrackTangent tangent(
-        //  (p2.position - p0.position)*k,
-        //  (p2.pressure - p0.pressure)*k,
-        //  (p2.tilt - p0.tilt)*k );
-        
-        // calculate tangent (with normalized position)
-        TPointD d = p2.position - p0.position;
-        double k = norm2(d);
-        k = k > TConsts::epsilon*TConsts::epsilon ? 1.0/sqrt(k) : 0.0;
-        TTrackTangent tangent(
-          d*k,
-          (p2.pressure - p0.pressure)*0.5,
-          (p2.tilt - p0.tilt)*0.5 );
-        
-        modifier->tangents.push_back(tangent);
-        subTrack.push_back(p1);
-        ++index;
-      }
-    }
-
-    track.resetChanges();
-
-    // release previous key point
-    modifier->savePoint.reset();
-
-    if (track.finished()) {
-      // finish
-      modifier->tangents.push_back(calcLastTangent(track));
-      subTrack.push_back(track.back());
-    } else {
-      // save key point
-      modifier->savePoint = savePoint;
-    }
+  if (!track.changed())
+    return;
+  
+  // update subTrack
+  int start = track.size() - track.pointsAdded;
+  if (start < 0) start = 0;
+  subTrack.truncate(start);
+  for(int i = start; i < track.size(); ++i)
+    subTrack.push_back(track[i], false);
+  
+  // update tangents
+  int tangentsStart = start - 1;
+  if (tangentsStart < 0) tangentsStart = 0;
+  modifier->tangents.resize(tangentsStart);
+  for(int i = tangentsStart; i < subTrack.size(); ++i)
+    modifier->tangents.push_back(calcTangent(subTrack, i));
+  
+  // fix points
+  if (track.fixedFinished()) {
+    subTrack.fix_all();
+  } else
+  if (track.fixedSize()) {
+    subTrack.fix_to(std::max(track.fixedSize() - 1, 1));
   }
+  
+  track.resetChanges();
 }
 
diff --git a/toonz/sources/tnztools/modifiers/modifiertest.cpp b/toonz/sources/tnztools/modifiers/modifiertest.cpp
index 2033a2b..7801f3b 100644
--- a/toonz/sources/tnztools/modifiers/modifiertest.cpp
+++ b/toonz/sources/tnztools/modifiers/modifiertest.cpp
@@ -52,7 +52,6 @@ TModifierTest::TModifierTest(int count, double radius)
     : count(count), radius(radius) {}
 
 void TModifierTest::modifyTrack(const TTrack &track,
-                                const TInputSavePoint::Holder &savePoint,
                                 TTrackList &outTracks) {
   const double segmentSize = 2.0 * M_PI / 10.0;
 
@@ -68,7 +67,7 @@ void TModifierTest::modifyTrack(const TTrack &track,
 
   Handler *handler = dynamic_cast<Handler *>(track.handler.getPointer());
   if (!handler) {
-    TInputModifier::modifyTrack(track, savePoint, outTracks);
+    TInputModifier::modifyTrack(track, outTracks);
     return;
   }
 
@@ -124,14 +123,19 @@ void TModifierTest::modifyTrack(const TTrack &track,
           double end  = 1.0 - 0.5 * step;
           for (double frac = step; frac < end; frac += step)
             subTrack.push_back(
-                subTrack.modifier->calcPoint((double)i - 1.0 + frac));
+                subTrack.modifier->calcPoint((double)i - 1.0 + frac), false);
         }
       }
-      subTrack.push_back(subTrack.modifier->calcPoint(i));
+      subTrack.push_back(subTrack.modifier->calcPoint(i), false);
     }
+    
+    // fix points
+    if (track.fixedSize())
+      subTrack.fix_to(
+        subTrack.floorIndex(subTrack.indexByOriginalIndex(track.fixedSize() - 1)) + 1 );
   }
 
   track.resetChanges();
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
index 61148f5..ad71c14 100644
--- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
@@ -1176,10 +1176,10 @@ bool ToonzRasterBrushTool::preLeftButtonDown() {
   m_inputmanager.clearModifiers();
   m_inputmanager.addModifier(TInputModifierP(m_modifierTangents.getPointer()));
   m_inputmanager.addModifier(TInputModifierP(m_modifierAssistants.getPointer()));
-  m_inputmanager.addModifier(TInputModifierP(m_modifierSegmentation.getPointer()));
 #ifndef NDEBUG
   m_inputmanager.addModifier(TInputModifierP(m_modifierTest.getPointer()));
 #endif
+  m_inputmanager.addModifier(TInputModifierP(m_modifierSegmentation.getPointer()));
 
   touchImage();
   if (m_isFrameCreated) {
@@ -1369,8 +1369,8 @@ void ToonzRasterBrushTool::inputSetBusy(bool busy) {
 
 //--------------------------------------------------------------------------------------------------
 
-void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack) {
-  if (!m_painting.active)
+void ToonzRasterBrushTool::inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track, bool firstTrack, bool preview) {
+  if (!m_painting.active || preview)
     return;
   
   TImageP img = getImage(true);
diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.h b/toonz/sources/tnztools/toonzrasterbrushtool.h
index d2adfef..b2e3cda 100644
--- a/toonz/sources/tnztools/toonzrasterbrushtool.h
+++ b/toonz/sources/tnztools/toonzrasterbrushtool.h
@@ -160,7 +160,7 @@ public:
                       const TInputState &state) override;
   void inputSetBusy(bool busy) override;
   void inputPaintTrackPoint(const TTrackPoint &point, const TTrack &track,
-                            bool firstTrack) override;
+                            bool firstTrack, bool preview) override;
   void inputInvalidateRect(const TRectD &bounds) override { invalidate(bounds); }
   TTool *inputGetTool() override { return this; };
 
diff --git a/toonz/sources/tnztools/track.cpp b/toonz/sources/tnztools/track.cpp
index 8d048d1..5af347a 100644
--- a/toonz/sources/tnztools/track.cpp
+++ b/toonz/sources/tnztools/track.cpp
@@ -42,7 +42,9 @@ TTrack::TTrack(
   hasPressure(hasPressure),
   hasTilt(hasTilt),
   pointsRemoved(),
-  pointsAdded()
+  pointsAdded(),
+  fixedPointsAdded(),
+  m_pointsFixed()
   { }
 
 TTrack::TTrack(const TTrackModifierP &modifier):
@@ -55,7 +57,9 @@ TTrack::TTrack(const TTrackModifierP &modifier):
   hasTilt(modifier->original.hasTilt),
   modifier(modifier),
   pointsRemoved(),
-  pointsAdded()
+  pointsAdded(),
+  fixedPointsAdded(),
+  m_pointsFixed()
   { }
 
 const TTrack*
@@ -82,7 +86,7 @@ TTrack::floorIndex(double index, double *outFrac) const {
 }
 
 void
-TTrack::push_back(const TTrackPoint &point) {
+TTrack::push_back(const TTrackPoint &point, bool fixed) {
   m_points.push_back(point);
   if (size() > 1) {
     const TTrackPoint &prev = *(m_points.rbegin() + 1);
@@ -100,12 +104,14 @@ TTrack::push_back(const TTrackPoint &point) {
     p.length = prev.length + sqrt(d.x*d.x + d.y*d.y);
   }
   ++pointsAdded;
+  if (fixed) fix_all();
 }
 
 void
 TTrack::pop_back(int count) {
   if (count > size()) count = size();
   if (count <= 0) return;
+  assert(size() - count >= m_pointsFixed);
   m_points.resize(size() - count);
   if (pointsAdded > count)
     { pointsAdded -= count; return; }
@@ -114,6 +120,15 @@ TTrack::pop_back(int count) {
   pointsRemoved += count;
 }
 
+void
+TTrack::fix_points(int count) {
+  count = std::min(count, previewSize());
+  assert(count >= 0);
+  if (count <= 0) return;
+  m_pointsFixed += count;
+  fixedPointsAdded += count;
+}
+
 
 TTrackPoint
 TTrack::calcPoint(double index) const {