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<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops); if (g_slist_length(these_stops) == 0 && drag->numSelected() == 1) { // if a single stop is selected, add between that stop and the next one GrDragger *dragger = (GrDragger *) drag->selected->data; for (GSList const* j = dragger->draggables; j != NULL; j = j->next) { GrDraggable *d = (GrDraggable *) j->data; SPGradient *gradient = sp_item_gradient (d->item, d->fill_or_stroke); SPGradient *vector = sp_gradient_get_forked_vector_if_necessary (gradient, false); SPStop *this_stop = sp_get_stop_i (vector, d->point_i); SPStop *next_stop = sp_next_stop (this_stop); if (this_stop && next_stop) { these_stops = g_slist_prepend (these_stops, this_stop); next_stops = g_slist_prepend (next_stops, next_stop); } } } // now actually create the new stops GSList *i = these_stops; GSList *j = next_stops; for (; i != NULL && j != NULL; i = i->next, j = j->next) { SPStop *this_stop = (SPStop *) i->data; SPStop *next_stop = (SPStop *) j->data; 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)); } } 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 drag->local_change = true; // select all the old selected and new created draggers drag->selectByCoords(coords); } g_slist_free (these_stops); g_slist_free (next_stops); }
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<Geom::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); }