static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb) { SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient")); SPStop *stop = get_selected_stop(vb); if (!stop) { return; } if (gradient->vector.stops.size() > 2) { // 2 is the minimum // if we delete first or last stop, move the next/previous to the edge if (stop->offset == 0) { SPStop *next = stop->getNextStop(); if (next) { next->offset = 0; sp_repr_set_css_double(next->getRepr(), "offset", 0); } } else if (stop->offset == 1) { SPStop *prev = stop->getPrevStop(); if (prev) { prev->offset = 1; sp_repr_set_css_double(prev->getRepr(), "offset", 1); } } gradient->getRepr()->removeChild(stop->getRepr()); sp_gradient_vector_widget_load_gradient(vb, gradient); update_stop_list(GTK_WIDGET(vb), gradient, NULL); DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, _("Delete gradient stop")); } }
static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb) { SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient")); verify_grad(gradient); SPStop *stop = get_selected_stop(vb); if (!stop) { return; } Inkscape::XML::Node *new_stop_repr = NULL; SPStop *next = stop->getNextStop(); if (next == NULL) { SPStop *prev = stop->getPrevStop(); if (prev != NULL) { next = stop; stop = prev; } } if (next != NULL) { new_stop_repr = stop->getRepr()->duplicate(gradient->getRepr()->document()); gradient->getRepr()->addChild(new_stop_repr, stop->getRepr()); } else { next = stop; new_stop_repr = stop->getPrevStop()->getRepr()->duplicate(gradient->getRepr()->document()); gradient->getRepr()->addChild(new_stop_repr, stop->getPrevStop()->getRepr()); } SPStop *newstop = reinterpret_cast<SPStop *>(gradient->document->getObjectByRepr(new_stop_repr)); newstop->offset = (stop->offset + next->offset) * 0.5 ; guint32 const c1 = stop->get_rgba32(); guint32 const c2 = next->get_rgba32(); guint32 cnew = sp_average_color(c1, c2); Inkscape::CSSOStringStream os; gchar c[64]; sp_svg_write_color(c, sizeof(c), cnew); gdouble opacity = static_cast<gdouble>(SP_RGBA32_A_F(cnew)); os << "stop-color:" << c << ";stop-opacity:" << opacity <<";"; newstop->getRepr()->setAttribute("style", os.str().c_str()); sp_repr_set_css_double( newstop->getRepr(), "offset", (double)newstop->offset); sp_gradient_vector_widget_load_gradient(vb, gradient); Inkscape::GC::release(new_stop_repr); update_stop_list(GTK_WIDGET(vb), gradient, newstop); GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offspn")); GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offslide")); gtk_widget_set_sensitive(offslide, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(offspin), TRUE); DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop")); }
/** * return true if this gradient is "equivalent" to that gradient. * Equivalent meaning they have the same stop count, same stop colors and same stop opacity * @param that - A gradient to compare this to */ bool SPGradient::isEquivalent(SPGradient *that) { //TODO Make this work for mesh gradients bool status = false; while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function if (this->getStopCount() != that->getStopCount()) { break; } if (this->hasStops() != that->hasStops()) { break; } if (!this->getVector() || !that->getVector()) { break; } if (this->isSwatch() != that->isSwatch()) { break; } if ( this->isSwatch() ){ // drop down to check stops. } else if ( (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) || (SP_IS_RADIALGRADIENT(this) && SP_IS_RADIALGRADIENT(that)) || (SP_IS_MESH(this) && SP_IS_MESH(that))) { if(!this->isAligned(that))break; } else { break; } // this should never happen, some unhandled type of gradient SPStop *as = this->getVector()->getFirstStop(); SPStop *bs = that->getVector()->getFirstStop(); bool effective = true; while (effective && (as && bs)) { if (!as->getEffectiveColor().isClose(bs->getEffectiveColor(), 0.001) || as->offset != bs->offset) { effective = false; break; } else { as = as->getNextStop(); bs = bs->getNextStop(); } } if (!effective) break; status = true; break; } return status; }
int SPGradient::getStopCount() const { int count = 0; for (SPStop *stop = const_cast<SPGradient*>(this)->getFirstStop(); stop && stop->getNextStop(); stop = stop->getNextStop()) { count++; } return count; }
// user selected existing stop from list static void sp_grad_edit_combo_box_changed (GtkComboBox * /*widget*/, GtkWidget *tbl) { SPStop *stop = get_selected_stop(tbl); if (!stop) { return; } blocked = TRUE; SelectedColor *csel = static_cast<SelectedColor*>(g_object_get_data(G_OBJECT(tbl), "cselector")); // set its color, from the stored array g_object_set_data(G_OBJECT(tbl), "updating_color", reinterpret_cast<void*>(1)); csel->setColorAlpha(stop->getEffectiveColor(), stop->opacity); g_object_set_data(G_OBJECT(tbl), "updating_color", reinterpret_cast<void*>(0)); GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offspn")); GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offslide")); GtkAdjustment *adj = static_cast<GtkAdjustment*>(g_object_get_data(G_OBJECT(tbl), "offset")); bool isEndStop = false; SPStop *prev = NULL; prev = stop->getPrevStop(); if (prev != NULL ) { gtk_adjustment_set_lower (adj, prev->offset); } else { isEndStop = true; gtk_adjustment_set_lower (adj, 0); } SPStop *next = NULL; next = stop->getNextStop(); if (next != NULL ) { gtk_adjustment_set_upper (adj, next->offset); } else { isEndStop = true; gtk_adjustment_set_upper (adj, 1.0); } //fixme: does this work on all possible input gradients? if (!isEndStop) { gtk_widget_set_sensitive(offslide, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(offspin), TRUE); } else { gtk_widget_set_sensitive(offslide, FALSE); gtk_widget_set_sensitive(GTK_WIDGET(offspin), FALSE); } gtk_adjustment_set_value(adj, stop->offset); gtk_adjustment_changed(adj); blocked = FALSE; }
static void gr_stop_set_offset(GtkComboBox * /*widget*/, GtkWidget *data) { SPStop *stop = get_selected_stop(data); if (!stop) { return; } EgeAdjustmentAction* act = (EgeAdjustmentAction *)g_object_get_data( G_OBJECT(data), "offset_action"); if (!act) { return; } GtkAdjustment *adj = ege_adjustment_action_get_adjustment(act); bool isEndStop = false; SPStop *prev = NULL; prev = stop->getPrevStop(); if (prev != NULL ) { gtk_adjustment_set_lower(adj, prev->offset); } else { isEndStop = true; gtk_adjustment_set_lower(adj, 0); } SPStop *next = NULL; next = stop->getNextStop(); if (next != NULL ) { gtk_adjustment_set_upper(adj, next->offset); } else { isEndStop = true; gtk_adjustment_set_upper(adj, 1.0); } blocked = TRUE; gtk_adjustment_set_value(adj, stop->offset); gtk_action_set_sensitive( GTK_ACTION(act), !isEndStop ); gtk_adjustment_changed(adj); blocked = FALSE; }