static Inkscape::XML::Node * sp_textpath_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPTextPath *textpath = SP_TEXTPATH(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:textPath"); } textpath->attributes.writeTo(repr); if (textpath->startOffset._set) { if (textpath->startOffset.unit == SVGLength::PERCENT) { Inkscape::SVGOStringStream os; os << (textpath->startOffset.computed * 100.0) << "%"; SP_OBJECT_REPR(textpath)->setAttribute("startOffset", os.str().c_str()); } else { /* FIXME: This logic looks rather undesirable if e.g. startOffset is to be in ems. */ sp_repr_set_svg_double(repr, "startOffset", textpath->startOffset.computed); } } if ( textpath->sourcePath->sourceHref ) repr->setAttribute("xlink:href", textpath->sourcePath->sourceHref); if ( flags&SP_OBJECT_WRITE_BUILD ) { GSList *l = NULL; for (SPObject* child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { Inkscape::XML::Node* c_repr=NULL; if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { c_repr = child->updateRepr(xml_doc, NULL, flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { c_repr = xml_doc->createTextNode(SP_STRING(child)->string.c_str()); } if ( c_repr ) l = g_slist_prepend(l, c_repr); } while ( l ) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); Inkscape::GC::release((Inkscape::XML::Node *) l->data); l = g_slist_remove(l, l->data); } } else { for (SPObject* child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { child->updateRepr(flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { SP_OBJECT_REPR(child)->setContent(SP_STRING(child)->string.c_str()); } } } if (((SPObjectClass *) textpath_parent_class)->write) ((SPObjectClass *) textpath_parent_class)->write(object, xml_doc, repr, flags); return repr; }
//FIXME: must work with text selection void text_remove_all_kerns() { SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::Selection *selection = sp_desktop_selection(desktop); if (selection->isEmpty()) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>text(s)</b> to remove kerns from.")); return; } bool did = false; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { SPObject *obj = SP_OBJECT(items->data); if (!SP_IS_TEXT(obj) && !SP_IS_TSPAN(obj) && !SP_IS_FLOWTEXT(obj)) { continue; } text_remove_all_kerns_recursively(obj); obj->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); did = true; } if (!did) { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("Select <b>text(s)</b> to remove kerns from.")); } else { sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, _("Remove manual kerns")); } }
static char * sp_tspan_description(SPItem *item) { g_return_val_if_fail(SP_IS_TSPAN(item), NULL); return g_strdup(_("<b>Text span</b>")); }
Inkscape::XML::Node* SPTSpan::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:tspan"); } this->attributes.writeTo(repr); if ( flags&SP_OBJECT_WRITE_BUILD ) { GSList *l = NULL; for (SPObject* child = this->firstChild() ; child ; child = child->getNext() ) { Inkscape::XML::Node* c_repr=NULL; if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { c_repr = child->updateRepr(xml_doc, NULL, flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { c_repr = xml_doc->createTextNode(SP_STRING(child)->string.c_str()); } if ( c_repr ) { l = g_slist_prepend(l, c_repr); } } while ( l ) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); Inkscape::GC::release((Inkscape::XML::Node *) l->data); l = g_slist_remove(l, l->data); } } else { for (SPObject* child = this->firstChild() ; child ; child = child->getNext() ) { if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { child->updateRepr(flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { child->getRepr()->setContent(SP_STRING(child)->string.c_str()); } } } SPItem::write(xml_doc, repr, flags); return repr; }
static Inkscape::XML::Node * sp_tspan_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { SPTSpan *tspan = SP_TSPAN(object); if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { repr = xml_doc->createElement("svg:tspan"); } tspan->attributes.writeTo(repr); if ( flags&SP_OBJECT_WRITE_BUILD ) { GSList *l = NULL; for (SPObject* child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { Inkscape::XML::Node* c_repr=NULL; if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { c_repr = child->updateRepr(xml_doc, NULL, flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { c_repr = xml_doc->createTextNode(SP_STRING(child)->string.c_str()); } if ( c_repr ) l = g_slist_prepend(l, c_repr); } while ( l ) { repr->addChild((Inkscape::XML::Node *) l->data, NULL); Inkscape::GC::release((Inkscape::XML::Node *) l->data); l = g_slist_remove(l, l->data); } } else { for (SPObject* child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { if ( SP_IS_TSPAN(child) || SP_IS_TREF(child) ) { child->updateRepr(flags); } else if ( SP_IS_TEXTPATH(child) ) { //c_repr = child->updateRepr(xml_doc, NULL, flags); // shouldn't happen } else if ( SP_IS_STRING(child) ) { SP_OBJECT_REPR(child)->setContent(SP_STRING(child)->string.c_str()); } } } if (((SPObjectClass *) tspan_parent_class)->write) ((SPObjectClass *) tspan_parent_class)->write(object, xml_doc, repr, flags); return repr; }
bool item_type_match (SPItem *item, GtkWidget *widget) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (SP_IS_RECT(item)) { return (type_checkbox (widget, "shapes") || type_checkbox (widget, "rects")); } else if (SP_IS_GENERICELLIPSE(item) || SP_IS_ELLIPSE(item) || SP_IS_ARC(item) || SP_IS_CIRCLE(item)) { return (type_checkbox (widget, "shapes") || type_checkbox (widget, "ellipses")); } else if (SP_IS_STAR(item) || SP_IS_POLYGON(item)) { return (type_checkbox (widget, "shapes") || type_checkbox (widget, "stars")); } else if (SP_IS_SPIRAL(item)) { return (type_checkbox (widget, "shapes") || type_checkbox (widget, "spirals")); } else if (SP_IS_PATH(item) || SP_IS_LINE(item) || SP_IS_POLYLINE(item)) { return (type_checkbox (widget, "paths")); } else if (SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item)) { return (type_checkbox (widget, "texts")); } else if (SP_IS_GROUP(item) && !desktop->isLayer(item) ) { // never select layers! return (type_checkbox (widget, "groups")); } else if (SP_IS_USE(item)) { return (type_checkbox (widget, "clones")); } else if (SP_IS_IMAGE(item)) { return (type_checkbox (widget, "images")); } else if (SP_IS_OFFSET(item)) { return (type_checkbox (widget, "offsets")); } return false; }
/* * Find all the fonts that are in the document but not available on the users system * and have been substituted for other fonts * * Return a list of SPItems where fonts have been substituted. * * Walk thru all the objects ... * a. Build up a list of the objects with fonts defined in the style attribute * b. Build up a list of the objects rendered fonts - taken for the objects layout/spans * If there are fonts in a. that are not in b. then those fonts have been substituted. */ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring *out) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; GSList *allList = NULL; GSList *outList = NULL; std::set<Glib::ustring> setErrors; std::set<Glib::ustring> setFontSpans; std::map<SPItem *, Glib::ustring> mapFontStyles; allList = get_all_items(NULL, doc->getRoot(), desktop, false, false, true, NULL); for (GSList *i = allList; i != NULL; i = i->next) { SPItem *item = SP_ITEM(i->data); SPStyle *style = item->style; Glib::ustring family = ""; if (is_top_level_text_object (item)) { // Should only need to check the first span, since the others should be covered by TSPAN's etc family = te_get_layout(item)->getFontFamily(0); setFontSpans.insert(family); } else if (SP_IS_TEXTPATH(item)) { SPTextPath const *textpath = SP_TEXTPATH(item); if (textpath->originalPath != NULL) { family = SP_TEXT(item->parent)->layout.getFontFamily(0); setFontSpans.insert(family); } } else if (SP_IS_TSPAN(item) || SP_IS_FLOWTSPAN(item)) { // is_part_of_text_subtree (item) // TSPAN layout comes from the parent->layout->_spans SPObject *parent_text = item; while (parent_text && !SP_IS_TEXT(parent_text)) { parent_text = parent_text->parent; } if (parent_text != NULL) { family = SP_TEXT(parent_text)->layout.getFontFamily(0); // Add all the spans fonts to the set gint ii = 0; for (SPObject *child = parent_text->firstChild() ; child ; child = child->getNext() ) { family = SP_TEXT(parent_text)->layout.getFontFamily(ii); setFontSpans.insert(family); ii++; } } } if (style) { gchar const *style_font = NULL; if (style->font_family.set) style_font = style->font_family.value; else if (style->font_specification.set) style_font = style->font_specification.value; else if (style->font_family.value) style_font = style->font_family.value; else if (style->font_specification.value) style_font = style->font_specification.value; if (style_font) { if (has_visible_text(item)) { mapFontStyles.insert(std::make_pair (item, style_font)); } } } } // Check if any document styles are not in the actual layout std::map<SPItem *, Glib::ustring>::const_iterator mapIter; for (mapIter = mapFontStyles.begin(); mapIter != mapFontStyles.end(); ++mapIter) { SPItem *item = mapIter->first; Glib::ustring fonts = mapIter->second; // CSS font fallbacks can have more that one font listed, split the font list std::vector<Glib::ustring> vFonts = Glib::Regex::split_simple("," , fonts); bool fontFound = false; for(size_t i=0; i<vFonts.size(); i++) { Glib::ustring font = vFonts[i]; // trim whitespace size_t startpos = font.find_first_not_of(" \n\r\t"); size_t endpos = font.find_last_not_of(" \n\r\t"); if(( std::string::npos == startpos ) || ( std::string::npos == endpos)) { continue; // empty font name } font = font.substr( startpos, endpos-startpos+1 ); std::set<Glib::ustring>::const_iterator iter = setFontSpans.find(font); if (iter != setFontSpans.end() || font == Glib::ustring("sans-serif") || font == Glib::ustring("Sans") || font == Glib::ustring("serif") || font == Glib::ustring("Serif") || font == Glib::ustring("monospace") || font == Glib::ustring("Monospace")) { fontFound = true; break; } } if (fontFound == false) { Glib::ustring subName = getSubstituteFontName(fonts); Glib::ustring err = Glib::ustring::compose( _("Font '%1' substituted with '%2'"), fonts.c_str(), subName.c_str()); setErrors.insert(err); outList = g_slist_prepend (outList, item); } } std::set<Glib::ustring>::const_iterator setIter; for (setIter = setErrors.begin(); setIter != setErrors.end(); ++setIter) { Glib::ustring err = (*setIter); out->append(err + "\n"); g_warning("%s", err.c_str()); } return outList; }