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); }
// TODO: So a solid brush is a gradient with a swatch and zero stops? // Should we derive a new class for that? Or at least make this method // virtual and move it out of the way? bool SPPaintServer::isSolid() const { bool solid = false; if (swatch && SP_IS_GRADIENT(this)) { SPGradient *grad = SP_GRADIENT(this); if ( grad->hasStops() && (grad->getStopCount() == 0) ) { solid = true; } } return solid; }
GtkWidget * gr_vector_list (SPDesktop *desktop, bool selection_empty, SPGradient *gr_selected, bool gr_multi) { SPDocument *document = sp_desktop_document (desktop); GtkWidget *om = gtk_option_menu_new (); GtkWidget *m = gtk_menu_new (); GSList *gl = NULL; const GSList *gradients = sp_document_get_resource_list (document, "gradient"); for (const GSList *i = gradients; i != NULL; i = i->next) { if (SP_GRADIENT_HAS_STOPS (i->data)) { gl = g_slist_prepend (gl, i->data); } } gl = g_slist_reverse (gl); guint pos = 0; guint idx = 0; if (!gl) { GtkWidget *l = gtk_label_new(""); gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients</small>")); GtkWidget *i = gtk_menu_item_new (); gtk_container_add (GTK_CONTAINER (i), l); gtk_widget_show (i); gtk_menu_append (GTK_MENU (m), i); gtk_widget_set_sensitive (om, FALSE); } else if (selection_empty) { GtkWidget *l = gtk_label_new(""); gtk_label_set_markup (GTK_LABEL(l), _("<small>Nothing selected</small>")); GtkWidget *i = gtk_menu_item_new (); gtk_container_add (GTK_CONTAINER (i), l); gtk_widget_show (i); gtk_menu_append (GTK_MENU (m), i); gtk_widget_set_sensitive (om, FALSE); } else { if (gr_selected == NULL) { GtkWidget *l = gtk_label_new(""); gtk_label_set_markup (GTK_LABEL(l), _("<small>No gradients in selection</small>")); GtkWidget *i = gtk_menu_item_new (); gtk_container_add (GTK_CONTAINER (i), l); gtk_widget_show (i); gtk_menu_append (GTK_MENU (m), i); } if (gr_multi) { GtkWidget *l = gtk_label_new(""); gtk_label_set_markup (GTK_LABEL(l), _("<small>Multiple gradients</small>")); GtkWidget *i = gtk_menu_item_new (); gtk_container_add (GTK_CONTAINER (i), l); gtk_widget_show (i); gtk_menu_append (GTK_MENU (m), i); } while (gl) { SPGradient *gradient = SP_GRADIENT (gl->data); gl = g_slist_remove (gl, gradient); GtkWidget *i = gtk_menu_item_new (); g_object_set_data (G_OBJECT (i), "gradient", gradient); g_signal_connect (G_OBJECT (i), "activate", G_CALLBACK (gr_item_activate), desktop); GtkWidget *image = sp_gradient_image_new (gradient); GtkWidget *hb = gtk_hbox_new (FALSE, 4); GtkWidget *l = gtk_label_new (""); gchar *label = gr_prepare_label (SP_OBJECT(gradient)); gtk_label_set_markup (GTK_LABEL(l), label); g_free (label); gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5); gtk_box_pack_start (GTK_BOX (hb), l, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hb), image, FALSE, FALSE, 0); gtk_widget_show_all (i); gtk_container_add (GTK_CONTAINER (i), hb); gtk_menu_append (GTK_MENU (m), i); if (gradient == gr_selected) { pos = idx; } idx ++; } gtk_widget_set_sensitive (om, TRUE); } gtk_option_menu_set_menu (GTK_OPTION_MENU (om), m); /* Select the current gradient, or the Multi/Nothing line */ if (gr_multi || gr_selected == NULL) gtk_option_menu_set_history (GTK_OPTION_MENU (om), 0); else gtk_option_menu_set_history (GTK_OPTION_MENU (om), pos); return om; }
void gr_read_selection (Inkscape::Selection *selection, GrDrag *drag, SPGradient **gr_selected, bool *gr_multi, SPGradientSpread *spr_selected, bool *spr_multi) { if (drag && drag->selected) { // GRADIENTFIXME: make this work for more than one selected dragger? GrDragger *dragger = (GrDragger*) drag->selected->data; for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger GrDraggable *draggable = (GrDraggable *) i->data; SPGradient *gradient = sp_item_gradient_get_vector (draggable->item, draggable->fill_or_stroke); SPGradientSpread spread = sp_item_gradient_get_spread (draggable->item, draggable->fill_or_stroke); if (gradient != *gr_selected) { if (*gr_selected != NULL) { *gr_multi = true; } else { *gr_selected = gradient; } } if (spread != *spr_selected) { if (*spr_selected != INT_MAX) { *spr_multi = true; } else { *spr_selected = spread; } } } return; } // If no selected dragger, read desktop selection for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { SPItem *item = SP_ITEM(i->data); SPStyle *style = SP_OBJECT_STYLE (item); if (style && (style->fill.isPaintserver())) { SPObject *server = SP_OBJECT_STYLE_FILL_SERVER (item); if (SP_IS_GRADIENT (server)) { SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false); SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server)); if (gradient != *gr_selected) { if (*gr_selected != NULL) { *gr_multi = true; } else { *gr_selected = gradient; } } if (spread != *spr_selected) { if (*spr_selected != INT_MAX) { *spr_multi = true; } else { *spr_selected = spread; } } } } if (style && (style->stroke.isPaintserver())) { SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER (item); if (SP_IS_GRADIENT (server)) { SPGradient *gradient = sp_gradient_get_vector (SP_GRADIENT (server), false); SPGradientSpread spread = sp_gradient_get_spread (SP_GRADIENT (server)); if (gradient != *gr_selected) { if (*gr_selected != NULL) { *gr_multi = true; } else { *gr_selected = gradient; } } if (spread != *spr_selected) { if (*spr_selected != INT_MAX) { *spr_multi = true; } else { *spr_selected = spread; } } } } } }
static void sp_fill_style_widget_update (SPWidget *spw, SPSelection *sel) { SPPaintSelector *psel; GtkWidget *fillrule; SPPaintSelectorMode pselmode; const GSList *objects, *l; SPObject *object; SPGradient *vector; gfloat c[5]; SPLinearGradient *lg; SPRadialGradient *rg; #if 0 NRPointF p0, p1, p2; #endif NRMatrixF fctm, gs2d; NRRectF fbb; if (g_object_get_data (G_OBJECT (spw), "update")) return; g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); psel = SP_PAINT_SELECTOR (g_object_get_data (G_OBJECT (spw), "paint-selector")); if (!sel || sp_selection_is_empty (sel)) { /* No objects, set empty */ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_EMPTY); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); return; } objects = sp_selection_item_list (sel); object = SP_OBJECT (objects->data); pselmode = (SPPaintSelectorMode)sp_fill_style_determine_paint_selector_mode (SP_OBJECT_STYLE (object)); for (l = objects->next; l != NULL; l = l->next) { SPPaintSelectorMode nextmode; nextmode = sp_fill_style_determine_paint_selector_mode (SP_OBJECT_STYLE (l->data)); if (nextmode != pselmode) { /* Multiple styles */ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); return; } } #ifdef SP_FS_VERBOSE g_print ("FillStyleWidget: paint selector mode %d\n", pselmode); #endif switch (pselmode) { case SP_PAINT_SELECTOR_MODE_NONE: /* No paint at all */ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_NONE); break; case SP_PAINT_SELECTOR_MODE_COLOR_RGB: sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_COLOR_RGB); sp_fill_style_get_average_color_rgba (objects, c); sp_paint_selector_set_color_rgba_floatv (psel, c); break; case SP_PAINT_SELECTOR_MODE_COLOR_CMYK: sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_COLOR_CMYK); sp_fill_style_get_average_color_cmyka (objects, c); sp_paint_selector_set_color_cmyka_floatv (psel, c); break; case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR: object = SP_OBJECT (objects->data); /* We know that all objects have lineargradient fill style */ vector = sp_gradient_get_vector (SP_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (object)), FALSE); for (l = objects->next; l != NULL; l = l->next) { SPObject *next; next = SP_OBJECT (l->data); if (sp_gradient_get_vector (SP_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (next)), FALSE) != vector) { /* Multiple vectors */ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); return; } } /* fixme: Probably we should set multiple mode here too */ sp_paint_selector_set_gradient_linear (psel, vector); sp_selection_bbox_document (sel, &fbb); sp_paint_selector_set_gradient_bbox (psel, fbb.x0, fbb.y0, fbb.x1, fbb.y1); /* fixme: This is plain wrong */ lg = SP_LINEARGRADIENT (SP_OBJECT_STYLE_FILL_SERVER (object)); sp_item_invoke_bbox (SP_ITEM (object), &fbb, NULL, TRUE); sp_item_i2doc_affine (SP_ITEM (object), &fctm); sp_gradient_get_gs2d_matrix_f (SP_GRADIENT (lg), &fctm, &fbb, &gs2d); sp_paint_selector_set_gradient_gs2d_matrix_f (psel, &gs2d); sp_paint_selector_set_gradient_properties (psel, SP_GRADIENT_UNITS (lg), SP_GRADIENT_SPREAD (lg)); sp_paint_selector_set_lgradient_position (psel, lg->x1.computed, lg->y1.computed, lg->x2.computed, lg->y2.computed); break; case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL: object = SP_OBJECT (objects->data); /* We know that all objects have radialgradient fill style */ vector = sp_gradient_get_vector (SP_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (object)), FALSE); for (l = objects->next; l != NULL; l = l->next) { SPObject *next; next = SP_OBJECT (l->data); if (sp_gradient_get_vector (SP_GRADIENT (SP_OBJECT_STYLE_FILL_SERVER (next)), FALSE) != vector) { /* Multiple vectors */ sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); return; } } /* fixme: Probably we should set multiple mode here too */ sp_paint_selector_set_gradient_radial (psel, vector); sp_selection_bbox_document (sel, &fbb); sp_paint_selector_set_gradient_bbox (psel, fbb.x0, fbb.y0, fbb.x1, fbb.y1); /* fixme: This is plain wrong */ rg = SP_RADIALGRADIENT (SP_OBJECT_STYLE_FILL_SERVER (object)); sp_item_invoke_bbox (SP_ITEM (object), &fbb, NULL, TRUE); sp_item_i2doc_affine (SP_ITEM (object), &fctm); sp_gradient_get_gs2d_matrix_f (SP_GRADIENT (rg), &fctm, &fbb, &gs2d); sp_paint_selector_set_gradient_gs2d_matrix_f (psel, &gs2d); sp_paint_selector_set_gradient_properties (psel, SP_GRADIENT_UNITS (rg), SP_GRADIENT_SPREAD (rg)); sp_paint_selector_set_rgradient_position (psel, rg->cx.computed, rg->cy.computed, rg->fx.computed, rg->fy.computed, rg->r.computed); break; default: sp_paint_selector_set_mode (psel, SP_PAINT_SELECTOR_MODE_MULTIPLE); break; } fillrule = GTK_WIDGET(g_object_get_data (G_OBJECT (spw), "fill-rule")); gtk_option_menu_set_history (GTK_OPTION_MENU (fillrule), (SP_OBJECT_STYLE (object)->fill_rule.computed == ART_WIND_RULE_NONZERO) ? 0 : 1); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); }