Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2014-06-04 09:51:39 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2014-06-04 10:03:42 +0400
commit812515b623be9179e67d97b84b10df587244d38c (patch)
tree92e11d33c238075686759b0b093d3b1d516121a7 /source/blender
parent5ee55caba58371d06e6437a493a93bdec804be45 (diff)
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.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp10
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.cpp30
-rw-r--r--source/blender/freestyle/intern/stroke/Stroke.h4
3 files changed, 30 insertions, 14 deletions
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index 7110eef9036..aa8c90cfd24 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 6629de0fa04..c85295e72bf 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 5e6c2fcf6cb..abbbcc32750 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.
*/