static void sp_fill_style_widget_paint_dragged (SPPaintSelector *psel, SPWidget *spw) { const GSList *items, *i; SPGradient *vector; gfloat c[5]; if (!spw->inkscape) return; if (g_object_get_data (G_OBJECT (spw), "update")) return; g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); #ifdef SP_FS_VERBOSE g_print ("FillStyleWidget: paint dragged\n"); #endif switch (psel->mode) { case SP_PAINT_SELECTOR_MODE_EMPTY: case SP_PAINT_SELECTOR_MODE_MULTIPLE: case SP_PAINT_SELECTOR_MODE_NONE: g_warning ("file %s: line %d: Paint %d should not emit 'dragged'", __FILE__, __LINE__, psel->mode); break; case SP_PAINT_SELECTOR_MODE_COLOR_RGB: sp_paint_selector_get_rgba_floatv (psel, c); items = sp_widget_get_item_list (spw); for (i = items; i != NULL; i = i->next) { sp_style_set_fill_color_rgba (SP_OBJECT_STYLE (i->data), c[0], c[1], c[2], c[3], TRUE, TRUE); } break; case SP_PAINT_SELECTOR_MODE_COLOR_CMYK: sp_paint_selector_get_cmyka_floatv (psel, c); items = sp_widget_get_item_list (spw); for (i = items; i != NULL; i = i->next) { sp_style_set_fill_color_cmyka (SP_OBJECT_STYLE (i->data), c[0], c[1], c[2], c[3], c[4], TRUE, TRUE); } break; case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR: vector = sp_paint_selector_get_gradient_vector (psel); vector = sp_gradient_ensure_vector_normalized (vector); items = sp_widget_get_item_list (spw); for (i = items; i != NULL; i = i->next) { SPGradient *lg; lg = sp_item_force_fill_lineargradient_vector (SP_ITEM (i->data), vector); sp_paint_selector_write_lineargradient (psel, SP_LINEARGRADIENT (lg), SP_ITEM (i->data)); } break; case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL: vector = sp_paint_selector_get_gradient_vector (psel); vector = sp_gradient_ensure_vector_normalized (vector); items = sp_widget_get_item_list (spw); for (i = items; i != NULL; i = i->next) { SPGradient *rg; rg = sp_item_force_fill_radialgradient_vector (SP_ITEM (i->data), vector); sp_paint_selector_write_radialgradient (psel, SP_RADIALGRADIENT (rg), SP_ITEM (i->data)); } break; default: g_warning ("file %s: line %d: Paint selector should not be in mode %d", __FILE__, __LINE__, psel->mode); break; } g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); }
/** * return true if this gradient is "aligned" to that gradient. * Aligned means that they have exactly the same coordinates and transform. * @param that - A gradient to compare this to */ bool SPGradient::isAligned(SPGradient *that) { bool status = false; /* Some gradients have coordinates/other values specified, some don't. yes/yes check the coordinates/other values no/no aligned (because both have all default values) yes/no not aligned no/yes not aligned It is NOT safe to just compare the computed values because if that field has not been set the computed value could be full of garbage. In theory the yes/no and no/yes cases could be aligned if the specified value matches the default value. */ while(1){ // not really a loop, used to avoid deep nesting or multiple exit points from function if(this->gradientTransform_set != that->gradientTransform_set) { break; } if(this->gradientTransform_set && (this->gradientTransform != that->gradientTransform)) { break; } if (SP_IS_LINEARGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) { SPLinearGradient *sg=SP_LINEARGRADIENT(this); SPLinearGradient *tg=SP_LINEARGRADIENT(that); if( sg->x1._set != tg->x1._set) { break; } if( sg->y1._set != tg->y1._set) { break; } if( sg->x2._set != tg->x2._set) { break; } if( sg->y2._set != tg->y2._set) { break; } if( sg->x1._set && sg->y1._set && sg->x2._set && sg->y2._set) { if( (sg->x1.computed != tg->x1.computed) || (sg->y1.computed != tg->y1.computed) || (sg->x2.computed != tg->x2.computed) || (sg->y2.computed != tg->y2.computed) ) { break; } } else if( sg->x1._set || sg->y1._set || sg->x2._set || sg->y2._set) { break; } // some mix of set and not set // none set? assume aligned and fall through } else if (SP_IS_RADIALGRADIENT(this) && SP_IS_LINEARGRADIENT(that)) { SPRadialGradient *sg=SP_RADIALGRADIENT(this); SPRadialGradient *tg=SP_RADIALGRADIENT(that); if( sg->cx._set != tg->cx._set) { break; } if( sg->cy._set != tg->cy._set) { break; } if( sg->r._set != tg->r._set) { break; } if( sg->fx._set != tg->fx._set) { break; } if( sg->fy._set != tg->fy._set) { break; } if( sg->cx._set && sg->cy._set && sg->fx._set && sg->fy._set && sg->r._set) { if( (sg->cx.computed != tg->cx.computed) || (sg->cy.computed != tg->cy.computed) || (sg->r.computed != tg->r.computed ) || (sg->fx.computed != tg->fx.computed) || (sg->fy.computed != tg->fy.computed) ) { break; } } else if( sg->cx._set || sg->cy._set || sg->fx._set || sg->fy._set || sg->r._set ) { break; } // some mix of set and not set // none set? assume aligned and fall through } else if (SP_IS_MESH(this) && SP_IS_MESH(that)) { SPMesh *sg=SP_MESH(this); SPMesh *tg=SP_MESH(that); if( sg->x._set != !tg->x._set) { break; } if( sg->y._set != !tg->y._set) { break; } if( sg->x._set && sg->y._set) { if( (sg->x.computed != tg->x.computed) || (sg->y.computed != tg->y.computed) ) { break; } } else if( sg->x._set || sg->y._set) { break; } // some mix of set and not set // none set? assume aligned and fall through } else { break; } status = true; break; } return status; }
static void sp_fill_style_widget_paint_changed (SPPaintSelector *psel, SPWidget *spw) { const GSList *items, *i, *r; GSList *reprs; SPCSSAttr *css; gfloat rgba[4], cmyka[5]; SPGradient *vector; gchar b[64]; if (g_object_get_data (G_OBJECT (spw), "update")) return; g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (TRUE)); #ifdef SP_FS_VERBOSE g_print ("FillStyleWidget: paint changed\n"); #endif if (spw->inkscape) { /* fixme: */ if (!SP_WIDGET_DOCUMENT (spw)) { g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); return; } reprs = NULL; items = sp_widget_get_item_list (spw); for (i = items; i != NULL; i = i->next) { reprs = g_slist_prepend (reprs, SP_OBJECT_REPR (i->data)); } } else { reprs = g_slist_prepend (NULL, spw->repr); items = NULL; } switch (psel->mode) { case SP_PAINT_SELECTOR_MODE_EMPTY: case SP_PAINT_SELECTOR_MODE_MULTIPLE: g_warning ("file %s: line %d: Paint %d should not emit 'changed'", __FILE__, __LINE__, psel->mode); break; case SP_PAINT_SELECTOR_MODE_NONE: css = sp_repr_css_attr_new (); sp_repr_css_set_property (css, "fill", "none"); for (r = reprs; r != NULL; r = r->next) { sp_repr_css_change_recursive ((SPRepr *) r->data, css, "style"); sp_repr_set_attr_recursive ((SPRepr *) r->data, "sodipodi:fill-cmyk", NULL); } sp_repr_css_attr_unref (css); if (spw->inkscape) sp_document_done (SP_WIDGET_DOCUMENT (spw)); break; case SP_PAINT_SELECTOR_MODE_COLOR_RGB: css = sp_repr_css_attr_new (); sp_paint_selector_get_rgba_floatv (psel, rgba); sp_svg_write_color (b, 64, SP_RGBA32_F_COMPOSE (rgba[0], rgba[1], rgba[2], 0.0)); sp_repr_css_set_property (css, "fill", b); g_snprintf (b, 64, "%g", rgba[3]); sp_repr_css_set_property (css, "fill-opacity", b); for (r = reprs; r != NULL; r = r->next) { sp_repr_set_attr_recursive ((SPRepr *) r->data, "sodipodi:fill-cmyk", NULL); sp_repr_css_change_recursive ((SPRepr *) r->data, css, "style"); } sp_repr_css_attr_unref (css); if (spw->inkscape) sp_document_done (SP_WIDGET_DOCUMENT (spw)); break; case SP_PAINT_SELECTOR_MODE_COLOR_CMYK: css = sp_repr_css_attr_new (); sp_paint_selector_get_cmyka_floatv (psel, cmyka); sp_color_cmyk_to_rgb_floatv (rgba, cmyka[0], cmyka[1], cmyka[2], cmyka[3]); sp_svg_write_color (b, 64, SP_RGBA32_F_COMPOSE (rgba[0], rgba[1], rgba[2], 0.0)); sp_repr_css_set_property (css, "fill", b); g_snprintf (b, 64, "%g", cmyka[4]); sp_repr_css_set_property (css, "fill-opacity", b); g_snprintf (b, 64, "(%g %g %g %g)", cmyka[0], cmyka[1], cmyka[2], cmyka[3]); for (r = reprs; r != NULL; r = r->next) { sp_repr_set_attr_recursive ((SPRepr *) r->data, "sodipodi:fill-cmyk", b); sp_repr_css_change_recursive ((SPRepr *) r->data, css, "style"); } sp_repr_css_attr_unref (css); if (spw->inkscape) sp_document_done (SP_WIDGET_DOCUMENT (spw)); break; case SP_PAINT_SELECTOR_MODE_GRADIENT_LINEAR: if (items) { vector = sp_paint_selector_get_gradient_vector (psel); if (!vector) { /* No vector in paint selector should mean that we just changed mode */ vector = sp_document_default_gradient_vector (SP_WIDGET_DOCUMENT (spw)); for (i = items; i != NULL; i = i->next) { sp_item_force_fill_lineargradient_vector (SP_ITEM (i->data), vector); } } else { vector = sp_gradient_ensure_vector_normalized (vector); for (i = items; i != NULL; i = i->next) { SPGradient *lg; lg = sp_item_force_fill_lineargradient_vector (SP_ITEM (i->data), vector); sp_paint_selector_write_lineargradient (psel, SP_LINEARGRADIENT (lg), SP_ITEM (i->data)); sp_object_invoke_write (SP_OBJECT (lg), SP_OBJECT_REPR (lg), SP_OBJECT_WRITE_EXT); } } sp_document_done (SP_WIDGET_DOCUMENT (spw)); } break; case SP_PAINT_SELECTOR_MODE_GRADIENT_RADIAL: if (items) { vector = sp_paint_selector_get_gradient_vector (psel); if (!vector) { /* No vector in paint selector should mean that we just changed mode */ vector = sp_document_default_gradient_vector (SP_WIDGET_DOCUMENT (spw)); for (i = items; i != NULL; i = i->next) { sp_item_force_fill_radialgradient_vector (SP_ITEM (i->data), vector); } } else { vector = sp_gradient_ensure_vector_normalized (vector); for (i = items; i != NULL; i = i->next) { SPGradient *rg; rg = sp_item_force_fill_radialgradient_vector (SP_ITEM (i->data), vector); sp_paint_selector_write_radialgradient (psel, SP_RADIALGRADIENT (rg), SP_ITEM (i->data)); sp_object_invoke_write (SP_OBJECT (rg), SP_OBJECT_REPR (rg), SP_OBJECT_WRITE_EXT); } } sp_document_done (SP_WIDGET_DOCUMENT (spw)); } break; default: g_warning ("file %s: line %d: Paint selector should not be in mode %d", __FILE__, __LINE__, psel->mode); break; } g_slist_free (reprs); g_object_set_data (G_OBJECT (spw), "update", GINT_TO_POINTER (FALSE)); }
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)); }