summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b0be2cc)
raw | patch | inline | side by side (parent: b0be2cc)
author | buliabyak <buliabyak@users.sourceforge.net> | |
Sun, 7 Oct 2007 06:02:30 +0000 (06:02 +0000) | ||
committer | buliabyak <buliabyak@users.sourceforge.net> | |
Sun, 7 Oct 2007 06:02:30 +0000 (06:02 +0000) |
src/gradient-context.cpp | patch | blob | history |
index 5d775b394ef85e2e51eac074b4bdc0013fc70d4a..e3e0fcf1a53c0838c6fbe5943f442c0ff6e0ca0e 100644 (file)
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
return (r / length);
}
-static void
-sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc)
+std::vector<NR::Point>
+sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSList **next_stops)
{
- bool added = false;
- SPDocument *doc = NULL;
- GrDrag *drag = rc->_grdrag;
-
- GSList *these_stops = NULL;
- GSList *next_stops = NULL;
-
std::vector<NR::Point> coords;
// for all selected draggers
// find the gradient
SPGradient *gradient = sp_item_gradient (d->item, d->fill_or_stroke);
SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false);
- doc = SP_OBJECT_DOCUMENT (vector);
// these draggable types cannot have a next draggabe to insert a stop between them
if (d->point_type == POINT_LG_END ||
coords.push_back(0.5*(dragger->point + dnext->point));
// if both adjacent draggers selected,
- if (!g_slist_find(these_stops, this_stop) && dnext && dnext->isSelected()) {
- added = true;
+ if (!g_slist_find(*these_stops, this_stop) && dnext && dnext->isSelected()) {
// do not insert a stop now, it will confuse the loop;
// just remember the stops
- these_stops = g_slist_prepend (these_stops, this_stop);
- next_stops = g_slist_prepend (next_stops, next_stop);
+ *these_stops = g_slist_prepend (*these_stops, this_stop);
+ *next_stops = g_slist_prepend (*next_stops, next_stop);
}
}
}
}
+ return coords;
+}
+
+static void
+sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc)
+{
+ SPDocument *doc = NULL;
+ GrDrag *drag = rc->_grdrag;
+
+ GSList *these_stops = NULL;
+ GSList *next_stops = NULL;
+
+ std::vector<NR::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops);
// now actually create the new stops
GSList *i = these_stops;
gfloat offset = 0.5*(this_stop->offset + next_stop->offset);
SPObject *parent = SP_OBJECT_PARENT(this_stop);
if (SP_IS_GRADIENT (parent)) {
+ doc = SP_OBJECT_DOCUMENT (parent);
sp_vector_add_stop (SP_GRADIENT (parent), this_stop, next_stop, offset);
sp_gradient_ensure_vector (SP_GRADIENT (parent));
}
}
- g_slist_free (these_stops);
- g_slist_free (next_stops);
-
- if (added && doc) {
+ if (g_slist_length(these_stops) > 0 && doc) {
sp_document_done (doc, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop"));
drag->updateDraggers();
// so that it does not automatically update draggers in idle loop, as this would deselect
// select all the old selected and new created draggers
drag->selectByCoords(coords);
}
+
+ g_slist_free (these_stops);
+ g_slist_free (next_stops);
}
+double sqr(double x) {return x*x;}
+
+static void
+sp_gradient_simplify(SPGradientContext *rc, double tolerance)
+{
+ SPDocument *doc = NULL;
+ GrDrag *drag = rc->_grdrag;
+
+ GSList *these_stops = NULL;
+ GSList *next_stops = NULL;
+
+ std::vector<NR::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops);
+
+ GSList *todel = NULL;
+
+ GSList *i = these_stops;
+ GSList *j = next_stops;
+ for (; i != NULL && j != NULL; i = i->next, j = j->next) {
+ SPStop *stop0 = (SPStop *) i->data;
+ SPStop *stop1 = (SPStop *) j->data;
+
+ gint i1 = g_slist_index(these_stops, stop1);
+ if (i1 != -1) {
+ GSList *next_next = g_slist_nth (next_stops, i1);
+ if (next_next) {
+ SPStop *stop2 = (SPStop *) next_next->data;
+
+ if (g_slist_find(todel, stop0) || g_slist_find(todel, stop2))
+ continue;
+
+ guint32 const c0 = sp_stop_get_rgba32(stop0);
+ guint32 const c2 = sp_stop_get_rgba32(stop2);
+ guint32 const c1r = sp_stop_get_rgba32(stop1);
+ guint32 c1 = average_color (c0, c2,
+ (stop1->offset - stop0->offset) / (stop2->offset - stop0->offset));
+
+ double diff =
+ sqr(SP_RGBA32_R_F(c1) - SP_RGBA32_R_F(c1r)) +
+ sqr(SP_RGBA32_G_F(c1) - SP_RGBA32_G_F(c1r)) +
+ sqr(SP_RGBA32_B_F(c1) - SP_RGBA32_B_F(c1r)) +
+ sqr(SP_RGBA32_A_F(c1) - SP_RGBA32_A_F(c1r));
+
+ if (diff < tolerance)
+ todel = g_slist_prepend (todel, stop1);
+ }
+ }
+ }
+
+ for (i = todel; i != NULL; i = i->next) {
+ SPStop *stop = (SPStop*) i->data;
+ doc = SP_OBJECT_DOCUMENT (stop);
+ Inkscape::XML::Node * parent = SP_OBJECT_REPR(stop)->parent();
+ parent->removeChild(SP_OBJECT_REPR(stop));
+ }
+
+ if (g_slist_length(todel) > 0) {
+ sp_document_done (doc, SP_VERB_CONTEXT_GRADIENT, _("Simplify gradient"));
+ drag->local_change = true;
+ drag->updateDraggers();
+ drag->selectByCoords(coords);
+ }
+
+ g_slist_free (todel);
+ g_slist_free (these_stops);
+ g_slist_free (next_stops);
+}
+
+
static void
sp_gradient_context_add_stop_near_point (SPGradientContext *rc, SPItem *item, NR::Point mouse_p, guint32 etime)
@@ -615,6 +688,14 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
}
break;
+ case GDK_L:
+ case GDK_l:
+ if (MOD__CTRL_ONLY && drag->isNonEmpty() && drag->hasSelection()) {
+ sp_gradient_simplify(rc, 1e-4);
+ ret = TRUE;
+ }
+ break;
+
case GDK_Escape:
if (drag->selected) {
drag->deselectAll();