void sp_textpath_to_text(SPObject *tp) { SPObject *text = SP_OBJECT_PARENT(tp); NRRect bbox; sp_item_invoke_bbox(SP_ITEM(text), &bbox, sp_item_i2doc_affine(SP_ITEM(text)), TRUE); Geom::Point xy(bbox.x0, bbox.y0); // make a list of textpath children GSList *tp_reprs = NULL; for (SPObject *o = SP_OBJECT(tp)->firstChild() ; o != NULL; o = o->next) { tp_reprs = g_slist_prepend(tp_reprs, SP_OBJECT_REPR(o)); } for ( GSList *i = tp_reprs ; i ; i = i->next ) { // make a copy of each textpath child Inkscape::XML::Node *copy = ((Inkscape::XML::Node *) i->data)->duplicate(SP_OBJECT_REPR(text)->document()); // remove the old repr from under textpath SP_OBJECT_REPR(tp)->removeChild((Inkscape::XML::Node *) i->data); // put its copy under text SP_OBJECT_REPR(text)->addChild(copy, NULL); // fixme: copy id } //remove textpath tp->deleteObject(); g_slist_free(tp_reprs); // set x/y on text /* fixme: Yuck, is this really the right test? */ if (xy[Geom::X] != 1e18 && xy[Geom::Y] != 1e18) { sp_repr_set_svg_double(SP_OBJECT_REPR(text), "x", xy[Geom::X]); sp_repr_set_svg_double(SP_OBJECT_REPR(text), "y", xy[Geom::Y]); } }
void text_unflow () { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) return; SPDocument *doc = sp_desktop_document (desktop); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::Selection *selection = sp_desktop_selection(desktop); if (!flowtext_in_selection(selection) || g_slist_length((GSList *) selection->itemList()) < 1) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>a flowed text</b> to unflow it.")); return; } GSList *new_objs = NULL; GSList *old_objs = NULL; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { if (!SP_IS_FLOWTEXT(SP_OBJECT(items->data))) { continue; } SPItem *flowtext = SP_ITEM(items->data); if (sp_te_get_string_multiline(flowtext) == NULL) { // flowtext is empty continue; } /* Create <text> */ Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create /* Set style */ rtext->setAttribute("style", SP_OBJECT_REPR(flowtext)->attribute("style")); // fixme: transfer style attrs too; and from descendants NRRect bbox; sp_item_invoke_bbox(SP_ITEM(flowtext), &bbox, sp_item_i2doc_affine(SP_ITEM(flowtext)), TRUE); Geom::Point xy(bbox.x0, bbox.y0); if (xy[Geom::X] != 1e18 && xy[Geom::Y] != 1e18) { sp_repr_set_svg_double(rtext, "x", xy[Geom::X]); sp_repr_set_svg_double(rtext, "y", xy[Geom::Y]); } /* Create <tspan> */ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); // otherwise, why bother creating the tspan? rtext->addChild(rtspan, NULL); gchar *text_string = sp_te_get_string_multiline(flowtext); Inkscape::XML::Node *text_repr = xml_doc->createTextNode(text_string); // FIXME: transfer all formatting!!! free(text_string); rtspan->appendChild(text_repr); SP_OBJECT_REPR(SP_OBJECT_PARENT(flowtext))->appendChild(rtext); SPObject *text_object = doc->getObjectByRepr(rtext); new_objs = g_slist_prepend (new_objs, text_object); old_objs = g_slist_prepend (old_objs, flowtext); Inkscape::GC::release(rtext); Inkscape::GC::release(rtspan); Inkscape::GC::release(text_repr); } selection->clear(); selection->setList(new_objs); for (GSList *i = old_objs; i; i = i->next) { SP_OBJECT(i->data)->deleteObject (true); } g_slist_free (old_objs); g_slist_free (new_objs); sp_document_done(doc, SP_VERB_CONTEXT_TEXT, _("Unflow flowed text")); }
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)); }