Fix a bunch of crashes in the vector clip tool

This commit is contained in:
Thomas Goyne 2014-06-03 10:07:19 -07:00
parent 5fcb287ed0
commit 0bf93ec263
4 changed files with 58 additions and 66 deletions

View file

@ -185,11 +185,11 @@ void Spline::MovePoint(iterator curve,int point,Vector2D pos) {
} }
} }
void Spline::GetPointList(std::vector<float>& points, std::vector<int>& first, std::vector<int>& count) { std::vector<float> Spline::GetPointList(std::vector<int>& first, std::vector<int>& count) {
points.clear();
first.clear(); first.clear();
count.clear(); count.clear();
std::vector<float> points;
points.reserve((size() + 1) * 2); points.reserve((size() + 1) * 2);
int curCount = 0; int curCount = 0;
@ -207,11 +207,12 @@ void Spline::GetPointList(std::vector<float>& points, std::vector<int>& first, s
} }
count.push_back(curCount); count.push_back(curCount);
return points;
} }
void Spline::GetPointList(std::vector<float> &points, iterator curve) { std::vector<float> Spline::GetPointList(iterator curve) {
points.clear(); std::vector<float> points;
if (curve == end()) return; if (curve == end()) return points;
switch (curve->type) { switch (curve->type) {
case SplineCurve::LINE: case SplineCurve::LINE:
points.push_back(curve->p1.X()); points.push_back(curve->p1.X());
@ -226,9 +227,10 @@ void Spline::GetPointList(std::vector<float> &points, iterator curve) {
default: break; default: break;
} }
return points;
} }
void Spline::GetClosestParametricPoint(Vector2D reference,iterator &curve,float &t,Vector2D &pt) { void Spline::GetClosestParametricPoint(Vector2D reference, iterator &curve, float &t, Vector2D &pt) {
curve = end(); curve = end();
t = 0.f; t = 0.f;
if (empty()) return; if (empty()) return;
@ -237,24 +239,22 @@ void Spline::GetClosestParametricPoint(Vector2D reference,iterator &curve,float
emplace_back(back().EndPoint(), front().p1); emplace_back(back().EndPoint(), front().p1);
float closest = std::numeric_limits<float>::infinity(); float closest = std::numeric_limits<float>::infinity();
for (auto cur = begin(); cur != end(); ++cur) { size_t idx = 0;
float param = cur->GetClosestParam(reference); for (size_t i = 0; i < size(); ++i) {
Vector2D p1 = cur->GetPoint(param); auto& cur = (*this)[i];
float param = cur.GetClosestParam(reference);
Vector2D p1 = cur.GetPoint(param);
float dist = (p1-reference).SquareLen(); float dist = (p1-reference).SquareLen();
if (dist < closest) { if (dist < closest) {
closest = dist; closest = dist;
t = param; t = param;
curve = cur; idx = i;
pt = p1; pt = p1;
} }
} }
if (&*curve == &back()) {
curve = end();
}
// Remove closing and return
pop_back(); pop_back();
curve = begin() + idx;
} }
Vector2D Spline::GetClosestPoint(Vector2D reference) { Vector2D Spline::GetClosestPoint(Vector2D reference) {

View file

@ -71,9 +71,9 @@ public:
void Smooth(float smooth=1.0f); void Smooth(float smooth=1.0f);
/// Gets a list of points in the curve /// Gets a list of points in the curve
void GetPointList(std::vector<float>& points, std::vector<int>& first, std::vector<int>& count); std::vector<float> GetPointList(std::vector<int>& first, std::vector<int>& count);
/// Gets a list of points in the curve /// Gets a list of points in the curve
void GetPointList(std::vector<float> &points, iterator curve); std::vector<float> GetPointList(iterator curve);
/// Get t value and curve of the point closest to reference /// Get t value and curve of the point closest to reference
void GetClosestParametricPoint(Vector2D reference, iterator& curve, float &t, Vector2D &point); void GetClosestParametricPoint(Vector2D reference, iterator& curve, float &t, Vector2D &point);
@ -92,18 +92,19 @@ public:
using std::vector<SplineCurve>::reverse_iterator; using std::vector<SplineCurve>::reverse_iterator;
using std::vector<SplineCurve>::const_reverse_iterator; using std::vector<SplineCurve>::const_reverse_iterator;
using std::vector<SplineCurve>::back;
using std::vector<SplineCurve>::begin; using std::vector<SplineCurve>::begin;
using std::vector<SplineCurve>::clear;
using std::vector<SplineCurve>::emplace_back;
using std::vector<SplineCurve>::empty;
using std::vector<SplineCurve>::end; using std::vector<SplineCurve>::end;
using std::vector<SplineCurve>::erase;
using std::vector<SplineCurve>::front;
using std::vector<SplineCurve>::insert;
using std::vector<SplineCurve>::operator[];
using std::vector<SplineCurve>::pop_back;
using std::vector<SplineCurve>::push_back;
using std::vector<SplineCurve>::rbegin; using std::vector<SplineCurve>::rbegin;
using std::vector<SplineCurve>::rend; using std::vector<SplineCurve>::rend;
using std::vector<SplineCurve>::size; using std::vector<SplineCurve>::size;
using std::vector<SplineCurve>::empty;
using std::vector<SplineCurve>::front;
using std::vector<SplineCurve>::back;
using std::vector<SplineCurve>::push_back;
using std::vector<SplineCurve>::pop_back;
using std::vector<SplineCurve>::emplace_back;
using std::vector<SplineCurve>::insert;
using std::vector<SplineCurve>::erase;
using std::vector<SplineCurve>::clear;
}; };

View file

@ -14,10 +14,6 @@
// //
// Aegisub Project http://www.aegisub.org/ // Aegisub Project http://www.aegisub.org/
/// @file visual_tool_vector_clip.cpp
/// @brief Vector clipping visual typesetting tool
/// @ingroup visual_ts
#include "visual_tool_vector_clip.h" #include "visual_tool_vector_clip.h"
#include "ass_dialogue.h" #include "ass_dialogue.h"
@ -90,11 +86,9 @@ void VisualToolVectorClip::Draw() {
if (spline.empty()) return; if (spline.empty()) return;
// Parse vector // Parse vector
std::vector<float> points;
std::vector<int> start; std::vector<int> start;
std::vector<int> count; std::vector<int> count;
auto points = spline.GetPointList(start, count);
spline.GetPointList(points, start, count);
assert(!start.empty()); assert(!start.empty());
assert(!count.empty()); assert(!count.empty());
@ -121,8 +115,7 @@ void VisualToolVectorClip::Draw() {
// Draw highlighted line // Draw highlighted line
if ((mode == 3 || mode == 4) && !active_feature && points.size() > 2) { if ((mode == 3 || mode == 4) && !active_feature && points.size() > 2) {
std::vector<float> highlighted_points; auto highlighted_points = spline.GetPointList(highlighted_curve);
spline.GetPointList(highlighted_points, highlighted_curve);
if (!highlighted_points.empty()) { if (!highlighted_points.empty()) {
gl.SetLineColour(colour[2], 1.f, 2); gl.SetLineColour(colour[2], 1.f, 2);
gl.DrawLineStrip(2, highlighted_points); gl.DrawLineStrip(2, highlighted_points);
@ -173,38 +166,39 @@ void VisualToolVectorClip::Draw() {
gl.DrawCircle(pt, 4); gl.DrawCircle(pt, 4);
} }
void VisualToolVectorClip::MakeFeature(Spline::iterator cur) { void VisualToolVectorClip::MakeFeature(size_t idx) {
auto feat = agi::make_unique<Feature>(); auto feat = agi::make_unique<Feature>();
feat->curve = cur; feat->idx = idx;
if (cur->type == SplineCurve::POINT) { auto const& curve = spline[idx];
feat->pos = cur->p1; if (curve.type == SplineCurve::POINT) {
feat->pos = curve.p1;
feat->type = DRAG_SMALL_CIRCLE; feat->type = DRAG_SMALL_CIRCLE;
feat->point = 0; feat->point = 0;
} }
else if (cur->type == SplineCurve::LINE) { else if (curve.type == SplineCurve::LINE) {
feat->pos = cur->p2; feat->pos = curve.p2;
feat->type = DRAG_SMALL_CIRCLE; feat->type = DRAG_SMALL_CIRCLE;
feat->point = 1; feat->point = 1;
} }
else if (cur->type == SplineCurve::BICUBIC) { else if (curve.type == SplineCurve::BICUBIC) {
// Control points // Control points
feat->pos = cur->p2; feat->pos = curve.p2;
feat->point = 1; feat->point = 1;
feat->type = DRAG_SMALL_SQUARE; feat->type = DRAG_SMALL_SQUARE;
features.push_back(*feat.release()); features.push_back(*feat.release());
feat = agi::make_unique<Feature>(); feat = agi::make_unique<Feature>();
feat->curve = cur; feat->idx = idx;
feat->pos = cur->p3; feat->pos = curve.p3;
feat->point = 2; feat->point = 2;
feat->type = DRAG_SMALL_SQUARE; feat->type = DRAG_SMALL_SQUARE;
features.push_back(*feat.release()); features.push_back(*feat.release());
// End point // End point
feat = agi::make_unique<Feature>(); feat = agi::make_unique<Feature>();
feat->curve = cur; feat->idx = idx;
feat->pos = cur->p4; feat->pos = curve.p4;
feat->point = 3; feat->point = 3;
feat->type = DRAG_SMALL_CIRCLE; feat->type = DRAG_SMALL_CIRCLE;
} }
@ -215,8 +209,8 @@ void VisualToolVectorClip::MakeFeatures() {
sel_features.clear(); sel_features.clear();
features.clear(); features.clear();
active_feature = nullptr; active_feature = nullptr;
for (auto it = spline.begin(); it != spline.end(); ++it) for (size_t i = 0; i < spline.size(); ++i)
MakeFeature(it); MakeFeature(i);
} }
void VisualToolVectorClip::Save() { void VisualToolVectorClip::Save() {
@ -239,30 +233,31 @@ void VisualToolVectorClip::Commit(wxString message) {
} }
void VisualToolVectorClip::UpdateDrag(Feature *feature) { void VisualToolVectorClip::UpdateDrag(Feature *feature) {
spline.MovePoint(feature->curve, feature->point, feature->pos); spline.MovePoint(spline.begin() + feature->idx, feature->point, feature->pos);
} }
bool VisualToolVectorClip::InitializeDrag(Feature *feature) { bool VisualToolVectorClip::InitializeDrag(Feature *feature) {
if (mode != 5) return true; if (mode != 5) return true;
if (feature->curve->type == SplineCurve::BICUBIC && (feature->point == 1 || feature->point == 2)) { auto curve = spline.begin() + feature->idx;
if (curve->type == SplineCurve::BICUBIC && (feature->point == 1 || feature->point == 2)) {
// Deleting bicubic curve handles, so convert to line // Deleting bicubic curve handles, so convert to line
feature->curve->type = SplineCurve::LINE; curve->type = SplineCurve::LINE;
feature->curve->p2 = feature->curve->p4; curve->p2 = curve->p4;
} }
else { else {
auto next = std::next(feature->curve); auto next = std::next(curve);
if (next != spline.end()) { if (next != spline.end()) {
if (feature->curve->type == SplineCurve::POINT) { if (curve->type == SplineCurve::POINT) {
next->p1 = next->EndPoint(); next->p1 = next->EndPoint();
next->type = SplineCurve::POINT; next->type = SplineCurve::POINT;
} }
else { else {
next->p1 = feature->curve->p1; next->p1 = curve->p1;
} }
} }
spline.erase(feature->curve); spline.erase(curve);
} }
active_feature = nullptr; active_feature = nullptr;
@ -297,7 +292,7 @@ bool VisualToolVectorClip::InitializeHold() {
spline.push_back(curve); spline.push_back(curve);
sel_features.clear(); sel_features.clear();
MakeFeature(--spline.end()); MakeFeature(spline.size() - 1);
UpdateHold(); UpdateHold();
return true; return true;
} }
@ -424,7 +419,7 @@ void VisualToolVectorClip::UpdateHold() {
float len = (last - mouse_pos).SquareLen(); float len = (last - mouse_pos).SquareLen();
if ((mode == 6 && len >= 900) || (mode == 7 && len >= 3600)) { if ((mode == 6 && len >= 900) || (mode == 7 && len >= 3600)) {
spline.emplace_back(last, mouse_pos); spline.emplace_back(last, mouse_pos);
MakeFeature(--spline.end()); MakeFeature(spline.size() - 1);
} }
} }

View file

@ -14,11 +14,6 @@
// //
// Aegisub Project http://www.aegisub.org/ // Aegisub Project http://www.aegisub.org/
/// @file visual_tool_vector_clip.h
/// @see visual_tool_vector_clip.cpp
/// @ingroup visual_ts
///
#include "visual_feature.h" #include "visual_feature.h"
#include "visual_tool.h" #include "visual_tool.h"
#include "spline.h" #include "spline.h"
@ -30,7 +25,7 @@ class wxToolBar;
/// in the spline /// in the spline
struct VisualToolVectorClipDraggableFeature final : public VisualDraggableFeature { struct VisualToolVectorClipDraggableFeature final : public VisualDraggableFeature {
/// Which curve in the spline this feature is a point on /// Which curve in the spline this feature is a point on
Spline::iterator curve; size_t idx = 0;
/// 0-3; indicates which part of the curve this point is /// 0-3; indicates which part of the curve this point is
int point = 0; int point = 0;
}; };
@ -51,7 +46,7 @@ class VisualToolVectorClip final : public VisualTool<VisualToolVectorClipDraggab
void Commit(wxString message="") override; void Commit(wxString message="") override;
void SelectAll(); void SelectAll();
void MakeFeature(Spline::iterator cur); void MakeFeature(size_t idx);
void MakeFeatures(); void MakeFeatures();
bool InitializeHold() override; bool InitializeHold() override;
@ -62,6 +57,7 @@ class VisualToolVectorClip final : public VisualTool<VisualToolVectorClipDraggab
void DoRefresh() override; void DoRefresh() override;
void Draw() override; void Draw() override;
public: public:
VisualToolVectorClip(VideoDisplay *parent, agi::Context *context); VisualToolVectorClip(VideoDisplay *parent, agi::Context *context);
void SetToolbar(wxToolBar *tb) override; void SetToolbar(wxToolBar *tb) override;