bool item_text_match (SPItem *item, const gchar *text, bool exact) { if (SP_OBJECT_REPR (item) == NULL) return false; if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { const gchar *item_text = sp_te_get_string_multiline (item); if (item_text == NULL) return false; bool ret; if (exact) { ret = ((bool) !strcasecmp(item_text, text)); } else { //FIXME: strcasestr ret = ((bool) (strstr(item_text, text) != NULL)); } g_free ((void*) item_text); return ret; } return false; }
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")); }
void text_flow_into_shape() { 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); SPItem *text = text_or_flowtext_in_selection(selection); SPItem *shape = shape_in_selection(selection); if (!text || !shape || g_slist_length((GSList *) selection->itemList()) < 2) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>a text</b> and one or more <b>paths or shapes</b> to flow text into frame.")); return; } if (SP_IS_TEXT(text)) { // remove transform from text, but recursively scale text's fontsize by the expansion SP_TEXT(text)->_adjustFontsizeRecursive(text, NR::expansion(SP_ITEM(text)->transform)); SP_OBJECT_REPR(text)->setAttribute("transform", NULL); } Inkscape::XML::Node *root_repr = xml_doc->createElement("svg:flowRoot"); root_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create root_repr->setAttribute("style", SP_OBJECT_REPR(text)->attribute("style")); // fixme: transfer style attrs too SP_OBJECT_REPR(SP_OBJECT_PARENT(shape))->appendChild(root_repr); SPObject *root_object = doc->getObjectByRepr(root_repr); g_return_if_fail(SP_IS_FLOWTEXT(root_object)); Inkscape::XML::Node *region_repr = xml_doc->createElement("svg:flowRegion"); root_repr->appendChild(region_repr); SPObject *object = doc->getObjectByRepr(region_repr); g_return_if_fail(SP_IS_FLOWREGION(object)); /* Add clones */ for (GSList *items = (GSList *) selection->itemList(); items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); if (SP_IS_SHAPE(item)){ Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); clone->setAttribute("x", "0"); clone->setAttribute("y", "0"); clone->setAttribute("xlink:href", g_strdup_printf("#%s", SP_OBJECT_REPR(item)->attribute("id"))); // add the new clone to the region region_repr->appendChild(clone); } } if (SP_IS_TEXT(text)) { // flow from text, as string Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); object = doc->getObjectByRepr(para_repr); g_return_if_fail(SP_IS_FLOWPARA(object)); Inkscape::Text::Layout const *layout = te_get_layout(text); Glib::ustring text_ustring = sp_te_get_string_multiline(text, layout->begin(), layout->end()); Inkscape::XML::Node *text_repr = xml_doc->createTextNode(text_ustring.c_str()); // FIXME: transfer all formatting! and convert newlines into flowParas! para_repr->appendChild(text_repr); Inkscape::GC::release(para_repr); Inkscape::GC::release(text_repr); } else { // reflow an already flowed text, preserving paras for (SPObject *o = SP_OBJECT(text)->children; o != NULL; o = o->next) { if (SP_IS_FLOWPARA(o)) { Inkscape::XML::Node *para_repr = SP_OBJECT_REPR(o)->duplicate(xml_doc); root_repr->appendChild(para_repr); object = doc->getObjectByRepr(para_repr); g_return_if_fail(SP_IS_FLOWPARA(object)); Inkscape::GC::release(para_repr); } } } SP_OBJECT(text)->deleteObject (true); sp_document_done(doc, SP_VERB_CONTEXT_TEXT, _("Flow text into shape")); sp_desktop_selection(desktop)->set(SP_ITEM(root_object)); Inkscape::GC::release(root_repr); Inkscape::GC::release(region_repr); }
static void sp_text_edit_dialog_read_selection ( GtkWidget *dlg, gboolean dostyle, gboolean docontent ) { if (g_object_get_data (G_OBJECT (dlg), "blocked")) return; g_object_set_data (G_OBJECT (dlg), "blocked", GINT_TO_POINTER (TRUE)); GtkWidget *notebook = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "notebook"); GtkWidget *textw = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "textw"); GtkWidget *fontsel = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "fontsel"); GtkWidget *preview = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "preview"); GtkWidget *apply = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "apply"); GtkWidget *def = (GtkWidget*)g_object_get_data (G_OBJECT (dlg), "default"); GtkTextBuffer *tb = (GtkTextBuffer*)g_object_get_data (G_OBJECT (dlg), "text"); SPItem *text = sp_ted_get_selected_text_item (); Inkscape::XML::Node *repr; if (text) { guint items = sp_ted_get_selected_text_count (); if (items == 1) { gtk_widget_set_sensitive (textw, TRUE); } else { gtk_widget_set_sensitive (textw, FALSE); } gtk_widget_set_sensitive (apply, FALSE); gtk_widget_set_sensitive (def, TRUE); if (docontent) { gchar *str; str = sp_te_get_string_multiline (text); if (str) { int pos; pos = 0; if (items == 1) { gtk_text_buffer_set_text (tb, str, strlen (str)); gtk_text_buffer_set_modified (tb, FALSE); } sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), str); g_free (str); } else { gtk_text_buffer_set_text (tb, "", 0); sp_font_preview_set_phrase (SP_FONT_PREVIEW (preview), NULL); } } // end of if (docontent) repr = SP_OBJECT_REPR (text); } else { gtk_widget_set_sensitive (textw, FALSE); gtk_widget_set_sensitive (apply, FALSE); gtk_widget_set_sensitive (def, FALSE); } if (dostyle) { // create temporary style SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection //int result_fontspec = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONT_SPECIFICATION); int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTFAMILY); int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTSTYLE); int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_FONTNUMBERS); // If querying returned nothing, read the style from the text tool prefs (default style for new texts) // (Ok to not get a font specification - must just rely on the family and style in that case) if (result_family == QUERY_STYLE_NOTHING || result_style == QUERY_STYLE_NOTHING || result_numbers == QUERY_STYLE_NOTHING) { sp_style_read_from_prefs(query, "/tools/text"); } // FIXME: process result_family/style == QUERY_STYLE_MULTIPLE_DIFFERENT by showing "Many" in the lists // Get a font_instance using the font-specification attribute stored in SPStyle if available font_instance *font = font_factory::Default()->FaceFromStyle(query); if (font) { // the font is oversized, so we need to pass the true size separately sp_font_selector_set_font (SP_FONT_SELECTOR (fontsel), font, query->font_size.computed); sp_font_preview_set_font (SP_FONT_PREVIEW (preview), font, SP_FONT_SELECTOR(fontsel)); font->Unref(); font=NULL; } GtkWidget *b; if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_START) { if (query->text_align.computed == SP_CSS_TEXT_ALIGN_JUSTIFY) { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), "text_anchor_justify" ); } else { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), "text_anchor_start" ); } } else if (query->text_anchor.computed == SP_CSS_TEXT_ANCHOR_MIDDLE) { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), "text_anchor_middle" ); } else { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), "text_anchor_end" ); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b), TRUE); if (query->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB) { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), INKSCAPE_STOCK_WRITING_MODE_LR ); } else { b = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), INKSCAPE_STOCK_WRITING_MODE_TB ); } gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b), TRUE); GtkWidget *combo = (GtkWidget*)g_object_get_data ( G_OBJECT (dlg), "line_spacing" ); double height; if (query->line_height.normal) height = Inkscape::Text::Layout::LINE_HEIGHT_NORMAL; else if (query->line_height.unit == SP_CSS_UNIT_PERCENT) height = query->line_height.value; else height = query->line_height.computed; gchar *sstr = g_strdup_printf ("%d%%", (int) floor(height * 100 + 0.5)); gtk_entry_set_text ((GtkEntry *) ((GtkCombo *) (combo))->entry, sstr); g_free(sstr); sp_style_unref(query); } g_object_set_data (G_OBJECT (dlg), "blocked", NULL); }