Commit: 812515b623be9179e67d97b84b10df587244d38c
Author: Tamito Kajiyama
Date:   Wed Jun 4 14:51:39 2014 +0900
https://developer.blender.org/rB812515b623be9179e67d97b84b10df587244d38c

Freestyle: Fix for a potential infinite loop in stroke resampling by vertex 
count.

Changes were made in Stroke::Resample(int) in C++ to prevent a potential 
infinite loop
caused by an inconsistency between Stroke::_Length and the stroke length 
computed
based on stroke vertices.  Such a stroke length inconsistency is usually caused 
by missing
calls of Stroke::UpdateLength() (i.e., API implementation bugs), but also may 
occur due
to scripting errors in user-defined style modules.  This commit is meant to 
help script
writters to identify the latter error cases.  Now Stroke.resample(int) may 
raise a runtime
error to signal an error condition.

===================================================================

M       source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
M       source/blender/freestyle/intern/stroke/Stroke.cpp
M       source/blender/freestyle/intern/stroke/Stroke.h

===================================================================

diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp 
b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index 7110eef..aa8c90c 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -151,10 +151,16 @@ static PyObject *Stroke_resample(BPy_Stroke *self, 
PyObject *args, PyObject *kwd
        float f;
 
        if (PyArg_ParseTupleAndKeywords(args, kwds, "i", (char **)kwlist_1, 
&i)) {
-               self->s->Resample(i);
+               if (self->s->Resample(i) < 0) {
+                       PyErr_SetString(PyExc_RuntimeError, "Stroke resampling 
(by vertex count) failed");
+                       return NULL;
+               }
        }
        else if (PyErr_Clear(), PyArg_ParseTupleAndKeywords(args, kwds, "f", 
(char **)kwlist_2, &f)) {
-               self->s->Resample(f);
+               if (self->s->Resample(f) < 0) {
+                       PyErr_SetString(PyExc_RuntimeError, "Stroke resampling 
(by vertex interval) failed");
+                       return NULL;
+               }
        }
        else {
                PyErr_SetString(PyExc_TypeError, "invalid argument");
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp 
b/source/blender/freestyle/intern/stroke/Stroke.cpp
index 6629de0..c85295e 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.cpp
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -508,11 +508,11 @@ public:
        }
 };
 
-void Stroke::Resample(int iNPoints)
+int Stroke::Resample(int iNPoints)
 {
-       int vertsize = strokeVerticesSize();
-       if (iNPoints <= vertsize)
-               return;
+       int NPointsToAdd = iNPoints - strokeVerticesSize();
+       if (NPointsToAdd <= 0)
+               return 0;
 
        StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
        StrokeInternal::StrokeVertexIterator next = it;
@@ -531,7 +531,7 @@ void Stroke::Resample(int iNPoints)
                Vec2r b((next)->getPoint());
                Vec2r vec_tmp(b - a);
                real norm_var = vec_tmp.norm();
-               int numberOfPointsToAdd = (int)floor((iNPoints - 
strokeVerticesSize()) * norm_var / _Length);
+               int numberOfPointsToAdd = (int)floor(NPointsToAdd * norm_var / 
_Length);
                float csampling = norm_var / (float)(numberOfPointsToAdd + 1);
                strokeSegments.push_back(StrokeSegment(it, next, norm_var, 
numberOfPointsToAdd, csampling));
                N += numberOfPointsToAdd;
@@ -543,9 +543,10 @@ void Stroke::Resample(int iNPoints)
        meanlength /= (float)nsegments;
 
        // if we don't have enough points let's resample finer some segments
-       int NPointsToAdd = iNPoints - vertsize;
        bool checkEveryone = false;
+       bool resampled;
        while (N < NPointsToAdd) {
+               resampled = false;
                for (vector<StrokeSegment>::iterator s = 
strokeSegments.begin(), send = strokeSegments.end(); s != send; ++s) {
                        if (s->_sampling == 0.0f)
                                continue;
@@ -556,14 +557,20 @@ void Stroke::Resample(int iNPoints)
                                //resample
                                s->_n = s->_n + 1;
                                s->_sampling = s->_length / (float)(s->_n + 1);
-                               s->_resampled = true;
+                               s->_resampled = resampled = true;
                                N++;
                                if (N == NPointsToAdd)
                                        break;
                        }
                }
+               if (checkEveryone && !resampled)
+                       break;
                checkEveryone = true;
        }
+       if (N < NPointsToAdd) {
+               // fatal error, likely because _Length is inconsistent with the 
stroke length computed with the vertices
+               return -1;
+       }
        //actually resample:
        for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = 
strokeSegments.end(); s != send; ++s) {
                newVertices.push_back(&(*(s->_begin)));
@@ -598,15 +605,17 @@ void Stroke::Resample(int iNPoints)
                delete _rep;
                _rep = new StrokeRep(this);
        }
+
+       return 0;
 }
 
-void Stroke::Resample(float iSampling)
+int Stroke::Resample(float iSampling)
 {
        //cerr << "old size :" << strokeVerticesSize() << endl;
        if (iSampling == 0)
-               return;
+               return 0;
        if (iSampling >= _sampling)
-               return;
+               return 0;
 
        _sampling = iSampling;
        // Resample...
@@ -655,6 +664,7 @@ void Stroke::Resample(float iSampling)
                delete _rep;
                _rep = new StrokeRep(this);
        }
+       return 0;
 }
 
 void Stroke::RemoveAllVertices()
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h 
b/source/blender/freestyle/intern/stroke/Stroke.h
index 5e6c2fc..abbbcc3 100644
--- a/source/blender/freestyle/intern/stroke/Stroke.h
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -588,7 +588,7 @@ public:
         *  \param iNPoints
         *    The number of vertices we eventually want in our stroke.
         */
-       void Resample(int iNPoints);
+       int Resample(int iNPoints);
 
        /*! Resampling method.
         *  Resamples the curve with a given sampling.
@@ -596,7 +596,7 @@ public:
         *  \param iSampling
         *    The new sampling value.  
         */
-       void Resample(float iSampling);
+       int Resample(float iSampling);
 
     /*! Removes all vertices from the Stroke.
      */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to