void spdc_create_single_dot(ToolBase *ec, Geom::Point const &pt, char const *tool, guint event_state) { g_return_if_fail(!strcmp(tool, "/tools/freehand/pen") || !strcmp(tool, "/tools/freehand/pencil")); Glib::ustring tool_path = tool; SPDesktop *desktop = ec->desktop; Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("sodipodi:type", "arc"); SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); // apply the tool's current style sp_desktop_apply_style_tool(desktop, repr, tool, false); // find out stroke width (TODO: is there an easier way??) double stroke_width = 3.0; gchar const *style_str = repr->attribute("style"); if (style_str) { SPStyle style(SP_ACTIVE_DOCUMENT); style.mergeString(style_str); stroke_width = style.stroke_width.computed; } // unset stroke and set fill color to former stroke color gchar * str; str = g_strdup_printf("fill:#%06x;stroke:none;", sp_desktop_get_color_tool(desktop, tool, false) >> 8); repr->setAttribute("style", str); g_free(str); // put the circle where the mouse click occurred and set the diameter to the // current stroke width, multiplied by the amount specified in the preferences Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Geom::Affine const i2d (item->i2dt_affine ()); Geom::Point pp = pt * i2d.inverse(); double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0); if (event_state & GDK_MOD1_MASK) { // TODO: We vary the dot size between 0.5*rad and 1.5*rad, where rad is the dot size // as specified in prefs. Very simple, but it might be sufficient in practice. If not, // we need to devise something more sophisticated. double s = g_random_double_range(-0.5, 0.5); rad *= (1 + s); } if (event_state & GDK_SHIFT_MASK) { // double the point size rad *= 2; } sp_repr_set_svg_double (repr, "sodipodi:cx", pp[Geom::X]); sp_repr_set_svg_double (repr, "sodipodi:cy", pp[Geom::Y]); sp_repr_set_svg_double (repr, "sodipodi:rx", rad * stroke_width); sp_repr_set_svg_double (repr, "sodipodi:ry", rad * stroke_width); item->updateRepr(); desktop->getSelection()->set(item); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating single dot")); DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE, _("Create single dot")); }
bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) { bool changed = false; if ( doc ) { // TODO debug g_message("FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP"); // TODO debug g_message(" base is [%s]", doc->getBase()); std::vector<Glib::ustring> brokenHrefs = findBrokenLinks(doc); if ( !brokenHrefs.empty() ) { // TODO debug g_message(" FOUND SOME LINKS %d", static_cast<int>(brokenHrefs.size())); for ( std::vector<Glib::ustring>::iterator it = brokenHrefs.begin(); it != brokenHrefs.end(); ++it ) { // TODO debug g_message(" [%s]", it->c_str()); } } std::map<Glib::ustring, Glib::ustring> mapping = locateLinks(doc->getBase(), brokenHrefs); for ( std::map<Glib::ustring, Glib::ustring>::iterator it = mapping.begin(); it != mapping.end(); ++it ) { // TODO debug g_message(" [%s] ==> {%s}", it->first.c_str(), it->second.c_str()); } bool savedUndoState = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, true); GSList const *images = doc->getResourceList("image"); for (GSList const *it = images; it; it = it->next) { Inkscape::XML::Node *ir = static_cast<SPObject *>(it->data)->getRepr(); gchar const *href = ir->attribute("xlink:href"); if ( href ) { // TODO debug g_message(" consider [%s]", href); if ( mapping.find(href) != mapping.end() ) { // TODO debug g_message(" Found a replacement"); ir->setAttribute( "xlink:href", mapping[href].c_str() ); if ( ir->attribute( "sodipodi:absref" ) ) { ir->setAttribute( "sodipodi:absref", 0 ); // Remove this attribute } SPObject *updated = doc->getObjectByRepr(ir); if (updated) { // force immediate update of dependant attributes updated->updateRepr(); } changed = true; } } } if ( changed ) { DocumentUndo::done( doc, SP_VERB_DIALOG_XML_EDITOR, _("Fixup broken links") ); } DocumentUndo::setUndoSensitive(doc, savedUndoState); } return changed; }
/** \brief This actually draws the grid. \param module The effect that was called (unused) \param document What should be edited. */ void Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { Inkscape::Selection * selection = ((SPDesktop *)document)->selection; Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100)); if (selection->isEmpty()) { /* get page size */ SPDocument * doc = document->doc(); bounding_area = Geom::Rect( Geom::Point(0,0), Geom::Point(doc->getWidth(), doc->getHeight()) ); } else { Geom::OptRect bounds = selection->visualBounds(); if (bounds) { bounding_area = *bounds; } gdouble doc_height = (document->doc())->getHeight(); Geom::Rect temprec = Geom::Rect(Geom::Point(bounding_area.min()[Geom::X], doc_height - bounding_area.min()[Geom::Y]), Geom::Point(bounding_area.max()[Geom::X], doc_height - bounding_area.max()[Geom::Y])); bounding_area = temprec; } float spacings[2] = { module->get_param_float("xspacing"), module->get_param_float("yspacing") }; float line_width = module->get_param_float("lineWidth"); float offsets[2] = { module->get_param_float("xoffset"), module->get_param_float("yoffset") }; Glib::ustring path_data(""); path_data = build_lines(bounding_area, offsets, spacings); Inkscape::XML::Document * xml_doc = document->doc()->getReprDoc(); //XML Tree being used directly here while it shouldn't be. Inkscape::XML::Node * current_layer = static_cast<SPDesktop *>(document)->currentLayer()->getRepr(); Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); path->setAttribute("d", path_data.c_str()); Glib::ustring style("fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"); style += ";stroke-width:"; gchar floatstring[64]; std::ostringstream stringstream; stringstream << line_width; sprintf(floatstring, "%s", stringstream.str().c_str()); style += floatstring; style += "pt"; path->setAttribute("style", style.c_str()); current_layer->appendChild(path); Inkscape::GC::release(path); return; }
Inkscape::XML::Node *box3d_side_convert_to_path(Box3DSide *side) { // TODO: Copy over all important attributes (see sp_selected_item_to_curved_repr() for an example) SPDocument *doc = side->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("d", side->getAttribute("d")); repr->setAttribute("style", side->getAttribute("style")); return repr; }
Persp3D *persp3d_create_xml_element(SPDocument *document, Persp3DImpl *dup) {// if dup is given, copy the attributes over SPDefs *defs = document->getDefs(); Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *repr; /* if no perspective is given, create a default one */ repr = xml_doc->createElement("inkscape:perspective"); repr->setAttribute("sodipodi:type", "inkscape:persp3d"); // Use 'user-units' double width = document->getWidth().value("px"); double height = document->getHeight().value("px"); if( document->getRoot()->viewBox_set ) { Geom::Rect vb = document->getRoot()->viewBox; width = vb.width(); height = vb.height(); } Proj::Pt2 proj_vp_x = Proj::Pt2 (0.0, height/2.0, 1.0); Proj::Pt2 proj_vp_y = Proj::Pt2 (0.0, 1000.0, 0.0); Proj::Pt2 proj_vp_z = Proj::Pt2 (width, height/2.0, 1.0); Proj::Pt2 proj_origin = Proj::Pt2 (width/2.0, height/3.0, 1.0 ); if (dup) { proj_vp_x = dup->tmat.column (Proj::X); proj_vp_y = dup->tmat.column (Proj::Y); proj_vp_z = dup->tmat.column (Proj::Z); proj_origin = dup->tmat.column (Proj::W); } gchar *str = NULL; str = proj_vp_x.coord_string(); repr->setAttribute("inkscape:vp_x", str); g_free (str); str = proj_vp_y.coord_string(); repr->setAttribute("inkscape:vp_y", str); g_free (str); str = proj_vp_z.coord_string(); repr->setAttribute("inkscape:vp_z", str); g_free (str); str = proj_origin.coord_string(); repr->setAttribute("inkscape:persp3d-origin", str); g_free (str); /* Append the new persp3d to defs */ defs->getRepr()->addChild(repr, NULL); Inkscape::GC::release(repr); return reinterpret_cast<Persp3D *>( defs->get_child_by_repr(repr) ); }
static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) { SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" )); if (DocumentUndo::getUndoSensitive(desktop->getDocument())) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/shapes/arc/open", ege_select_one_action_get_active(act) != 0); } // quit if run by the attr_changed listener if (g_object_get_data( tbl, "freeze" )) { return; } // in turn, prevent listener from responding g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); bool modmade = false; if ( ege_select_one_action_get_active(act) != 0 ) { std::vector<SPItem*> itemlist=desktop->getSelection()->itemList(); for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){ SPItem *item = *i; if (SP_IS_GENERICELLIPSE(item)) { Inkscape::XML::Node *repr = item->getRepr(); repr->setAttribute("sodipodi:open", "true"); item->updateRepr(); modmade = true; } } } else { std::vector<SPItem*> itemlist=desktop->getSelection()->itemList(); for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){ SPItem *item = *i; if (SP_IS_GENERICELLIPSE(item)) { Inkscape::XML::Node *repr = item->getRepr(); repr->setAttribute("sodipodi:open", NULL); item->updateRepr(); modmade = true; } } } if (modmade) { DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_ARC, _("Arc: Change open/closed")); } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); }
/** * Writes the gradient's internal vector (whether from its own stops, or * inherited from refs) into the gradient repr as svg:stop elements. */ void sp_gradient_repr_write_vector(SPGradient *gr) { g_return_if_fail(gr != NULL); g_return_if_fail(SP_IS_GRADIENT(gr)); Inkscape::XML::Document *xml_doc = gr->document->getReprDoc(); Inkscape::XML::Node *repr = gr->getRepr(); /* We have to be careful, as vector may be our own, so construct repr list at first */ GSList *cl = NULL; for (guint i = 0; i < gr->vector.stops.size(); i++) { Inkscape::CSSOStringStream os; Inkscape::XML::Node *child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", gr->vector.stops[i].offset); /* strictly speaking, offset an SVG <number> rather than a CSS one, but exponents make no * sense for offset proportions. */ os << "stop-color:" << gr->vector.stops[i].color.toString() << ";stop-opacity:" << gr->vector.stops[i].opacity; child->setAttribute("style", os.str().c_str()); /* Order will be reversed here */ cl = g_slist_prepend(cl, child); } sp_gradient_repr_clear_vector(gr); /* And insert new children from list */ while (cl) { Inkscape::XML::Node *child = static_cast<Inkscape::XML::Node *>(cl->data); repr->addChild(child, NULL); Inkscape::GC::release(child); cl = g_slist_remove(cl, child); } }
// Create a mask element (using passed elements), add it to <defs> const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath"); repr->setAttribute("clipPathUnits", "userSpaceOnUse"); defsrepr->appendChild(repr); const gchar *id = repr->attribute("id"); SPObject *clip_path_object = document->getObjectById(id); for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { Geom::Affine transform (item->transform); transform *= (*applyTransform); item->doWriteTransform(item->getRepr(), transform); } } Inkscape::GC::release(repr); return id; }
Inkscape::XML::Node *Parameter::document_param_node(SPDocument * doc) { Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node * defs = doc->getDefs()->getRepr(); Inkscape::XML::Node * params = NULL; GQuark const name_quark = g_quark_from_string("inkscape:extension-params"); for (Inkscape::XML::Node * child = defs->firstChild(); child != NULL; child = child->next()) { if ((GQuark)child->code() == name_quark && !strcmp(child->attribute("extension"), extension->get_id())) { params = child; break; } } if (params == NULL) { params = xml_doc->createElement("inkscape:extension-param"); params->setAttribute("extension", extension->get_id()); defs->appendChild(params); Inkscape::GC::release(params); } return params; }
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem) { g_return_if_fail(lpeitem != NULL); SPMask * mask = lpeitem->mask_ref->getObject(); if(mask) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild())); } SPClipPath * clipPath = lpeitem->clip_ref->getObject(); if(clipPath) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild())); } if (SP_IS_GROUP(lpeitem)) { GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); if (SP_IS_LPE_ITEM(subitem)) { sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem)); } } } else if (SP_IS_PATH(lpeitem)) { Inkscape::XML::Node *pathrepr = lpeitem->getRepr(); if ( !pathrepr->attribute("inkscape:original-d") ) { pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d")); } } }
// Create a mask element (using passed elements), add it to <defs> const gchar * sp_clippath_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document); Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath"); repr->setAttribute("clipPathUnits", "userSpaceOnUse"); defsrepr->appendChild(repr); const gchar *id = repr->attribute("id"); SPObject *clip_path_object = document->getObjectById(id); for (GSList *it = reprs; it != NULL; it = it->next) { Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data); SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { Geom::Matrix transform (item->transform); transform *= (*applyTransform); sp_item_write_transform(item, SP_OBJECT_REPR(item), transform); } } Inkscape::GC::release(repr); return id; }
static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) { GSList const *item_list = sp_item_group_item_list(SP_GROUP(group)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); if (SP_IS_GROUP(subitem)) { sp_group_perform_patheffect(SP_GROUP(subitem), topgroup, write); } else if (SP_IS_SHAPE(subitem)) { SPCurve * c = NULL; if (SP_IS_PATH(subitem)) { c = SP_PATH(subitem)->get_original_curve(); } else { c = SP_SHAPE(subitem)->getCurve(); } // only run LPEs when the shape has a curve defined if (c) { sp_lpe_item_perform_path_effect(SP_LPE_ITEM(topgroup), c); SP_SHAPE(subitem)->setCurve(c, TRUE); if (write) { Inkscape::XML::Node *repr = subitem->getRepr(); gchar *str = sp_svg_write_path(c->get_pathvector()); repr->setAttribute("d", str); #ifdef GROUP_VERBOSE g_message("sp_group_perform_patheffect writes 'd' attribute"); #endif g_free(str); } c->unref(); } } } }
static void sp_item_create_link(GtkMenuItem *menuitem, SPItem *item) { g_assert(SP_IS_ITEM(item)); g_assert(!SP_IS_ANCHOR(item)); SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop"); g_return_if_fail(desktop != NULL); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc()); Inkscape::XML::Node *repr = xml_doc->createElement("svg:a"); SP_OBJECT_REPR(SP_OBJECT_PARENT(item))->addChild(repr, SP_OBJECT_REPR(item)); SPObject *object = SP_OBJECT_DOCUMENT(item)->getObjectByRepr(repr); g_return_if_fail(SP_IS_ANCHOR(object)); const char *id = SP_OBJECT_REPR(item)->attribute("id"); Inkscape::XML::Node *child = SP_OBJECT_REPR(item)->duplicate(xml_doc); SP_OBJECT(item)->deleteObject(false); repr->addChild(child, NULL); child->setAttribute("id", id); Inkscape::GC::release(repr); Inkscape::GC::release(child); sp_document_done(SP_OBJECT_DOCUMENT(object), SP_VERB_NONE, _("Create link")); sp_object_attributes_dialog(object, "SPAnchor"); sp_desktop_selection(desktop)->set(SP_ITEM(object)); }
void SPStar::update_patheffect(bool write) { this->set_shape(); if (write) { Inkscape::XML::Node *repr = this->getRepr(); if ( this->_curve != NULL ) { gchar *str = sp_svg_write_path(this->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } } this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); }
static void sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *sel) { SPDocument *doc = sp_gradient_vector_selector_get_document (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); if (!doc) return; SPGradient *gr = sp_gradient_vector_selector_get_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = NULL; if (gr) { repr = gr->getRepr()->duplicate(xml_doc); } else { repr = xml_doc->createElement("svg:linearGradient"); Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "0"); stop->setAttribute("style", "stop-color:#000;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "1"); stop->setAttribute("style", "stop-color:#fff;stop-opacity:1;"); repr->appendChild(stop); Inkscape::GC::release(stop); } doc->getDefs()->getRepr()->addChild(repr, NULL); Glib::ustring old_id = gr->getId(); gr = SP_GRADIENT(doc->getObjectByRepr(repr)); // Rename the new gradients id to be similar to the cloned gradients rename_id(gr, old_id); sp_gradient_vector_selector_set_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors), doc, gr); sel->selectGradientInTree(gr); Inkscape::GC::release(repr); }
static void sp_path_update_patheffect(SPLPEItem *lpeitem, bool write) { SPShape * const shape = (SPShape *) lpeitem; Inkscape::XML::Node *repr = shape->getRepr(); #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect"); #endif if (shape->_curve_before_lpe && sp_lpe_item_has_path_effect_recursive(lpeitem)) { SPCurve *curve = shape->_curve_before_lpe->copy(); /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe. * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ shape->setCurveInsync(curve, TRUE); bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM(shape), curve); if (success && write) { // could also do shape->getRepr()->updateRepr(); but only the d attribute needs updating. #ifdef PATH_VERBOSE g_message("sp_path_update_patheffect writes 'd' attribute"); #endif if ( shape->_curve != NULL ) { gchar *str = sp_svg_write_path(shape->_curve->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { repr->setAttribute("d", NULL); } } else if (!success) { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = repr->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { shape->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); curve->unref(); } }
void Preferences::_setRawValue(Glib::ustring const &path, gchar const *value) { // create node and attribute keys Glib::ustring node_key, attr_key; _keySplit(path, node_key, attr_key); // set the attribute Inkscape::XML::Node *node = _getNode(node_key, true); node->setAttribute(attr_key.data(), value); }
static void verify_grad(SPGradient *gradient) { int i = 0; SPStop *stop = NULL; /* count stops */ for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { i++; stop = SP_STOP(ochild); } } Inkscape::XML::Document *xml_doc; xml_doc = gradient->getRepr()->document(); if (i < 1) { Inkscape::CSSOStringStream os; os << "stop-color: #000000;stop-opacity:" << 1.0 << ";"; Inkscape::XML::Node *child; child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", 0.0); child->setAttribute("style", os.str().c_str()); gradient->getRepr()->addChild(child, NULL); Inkscape::GC::release(child); child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", 1.0); child->setAttribute("style", os.str().c_str()); gradient->getRepr()->addChild(child, NULL); Inkscape::GC::release(child); return; } if (i < 2) { sp_repr_set_css_double(stop->getRepr(), "offset", 0.0); Inkscape::XML::Node *child = stop->getRepr()->duplicate(gradient->getRepr()->document()); sp_repr_set_css_double(child, "offset", 1.0); gradient->getRepr()->addChild(child, stop->getRepr()); Inkscape::GC::release(child); } }
Inkscape::XML::Node * Parameter::new_child (Inkscape::XML::Node * parent) { Inkscape::XML::Node * retval; retval = parent->document()->createElement("inkscape:extension-param"); retval->setAttribute("name", _name); parent->appendChild(retval); Inkscape::GC::release(retval); return retval; }
/* If the viewBox is missing, set one */ void Metafile::setViewBoxIfMissing(SPDocument *doc) { if (doc && !doc->getRoot()->viewBox_set) { bool saved = Inkscape::DocumentUndo::getUndoSensitive(doc); Inkscape::DocumentUndo::setUndoSensitive(doc, false); doc->ensureUpToDate(); // Set document unit Inkscape::XML::Node *repr = sp_document_namedview(doc, 0)->getRepr(); Inkscape::SVGOStringStream os; Inkscape::Util::Unit const* doc_unit = doc->getWidth().unit; os << doc_unit->abbr; repr->setAttribute("inkscape:document-units", os.str().c_str()); // Set viewBox doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc_unit), doc->getHeight().value(doc_unit))); doc->ensureUpToDate(); // Scale and translate objects double scale = Inkscape::Util::Quantity::convert(1, "px", doc_unit); Inkscape::UI::ShapeEditor::blockSetItem(true); double dh; if(SP_ACTIVE_DOCUMENT){ // for file menu open or import, or paste from clipboard dh = SP_ACTIVE_DOCUMENT->getHeight().value("px"); } else { // for open via --file on command line dh = doc->getHeight().value("px"); } // These should not affect input, but they do, so set them to a neutral state Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool transform_stroke = prefs->getBool("/options/transform/stroke", true); bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); bool transform_pattern = prefs->getBool("/options/transform/pattern", true); bool transform_gradient = prefs->getBool("/options/transform/gradient", true); prefs->setBool("/options/transform/stroke", true); prefs->setBool("/options/transform/rectcorners", true); prefs->setBool("/options/transform/pattern", true); prefs->setBool("/options/transform/gradient", true); doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, dh), true); Inkscape::UI::ShapeEditor::blockSetItem(false); // restore options prefs->setBool("/options/transform/stroke", transform_stroke); prefs->setBool("/options/transform/rectcorners", transform_rectcorners); prefs->setBool("/options/transform/pattern", transform_pattern); prefs->setBool("/options/transform/gradient", transform_gradient); Inkscape::DocumentUndo::setUndoSensitive(doc, saved); } }
void SPLPEItem::apply_to_clippath(SPItem *item) { SPClipPath *clipPath = item->clip_ref->getObject(); if(clipPath) { SPObject * clip_data = clipPath->firstChild(); SPCurve * clip_curve = NULL; if (SP_IS_PATH(clip_data)) { clip_curve = SP_PATH(clip_data)->get_original_curve(); } else if(SP_IS_SHAPE(clip_data)) { clip_curve = SP_SHAPE(clip_data)->getCurve(); } else if(SP_IS_GROUP(clip_data)) { apply_to_clip_or_mask_group(SP_ITEM(clip_data), item); return; } if(clip_curve) { bool success = false; if(SP_IS_GROUP(this)){ clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this))); success = this->performPathEffect(clip_curve); clip_curve->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse()); } else { success = this->performPathEffect(clip_curve); } Inkscape::XML::Node *reprClip = clip_data->getRepr(); if (success) { gchar *str = sp_svg_write_path(clip_curve->get_pathvector()); reprClip->setAttribute("d", str); g_free(str); } else { // LPE was unsuccesfull. Read the old 'd'-attribute. if (gchar const * value = reprClip->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new SPCurve(pv); if (oldcurve) { SP_SHAPE(clip_data)->setCurve(oldcurve, TRUE); oldcurve->unref(); } } } clip_curve->unref(); } } if(SP_IS_GROUP(item)){ GSList const *item_list = sp_item_group_item_list(SP_GROUP(item)); for ( GSList const *iter = item_list; iter; iter = iter->next ) { SPObject *subitem = static_cast<SPObject *>(iter->data); apply_to_clippath(SP_ITEM(subitem)); } } }
void Effect::createAndApply(const char* name, SPDocument *doc, SPItem *item) { // Path effect definition Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect"); repr->setAttribute("effect", name); SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute const gchar * repr_id = repr->attribute("id"); Inkscape::GC::release(repr); gchar *href = g_strdup_printf("#%s", repr_id); sp_lpe_item_add_path_effect(SP_LPE_ITEM(item), href, true); g_free(href); }
void sp_document_set_uri(SPDocument *document, gchar const *uri) { g_return_if_fail(document != NULL); if (document->name) { g_free(document->name); document->name = NULL; } if (document->base) { g_free(document->base); document->base = NULL; } if (document->uri) { g_free(document->uri); document->uri = NULL; } if (uri) { #ifndef WIN32 prepend_current_dir_if_relative(&(document->uri), uri); #else // FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test! document->uri = g_strdup(uri); #endif /* fixme: Think, what this means for images (Lauris) */ document->base = g_path_get_dirname(document->uri); document->name = g_path_get_basename(document->uri); } else { document->uri = g_strdup_printf(_("Unnamed document %d"), ++doc_count); document->base = NULL; document->name = g_strdup(document->uri); } // Update saveable repr attributes. Inkscape::XML::Node *repr = sp_document_repr_root(document); // changing uri in the document repr must not be not undoable bool saved = sp_document_get_undo_sensitive(document); sp_document_set_undo_sensitive(document, false); repr->setAttribute("sodipodi:docname", document->name); sp_document_set_undo_sensitive(document, saved); document->priv->uri_set_signal.emit(document->uri); }
Inkscape::XML::Node * sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) { if (!item) return NULL; Inkscape::XML::Document *xml_doc = item->getRepr()->document(); if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { // Special treatment for text: convert each glyph to separate path, then group the paths Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g"); g_repr->setAttribute("transform", item->getRepr()->attribute("transform")); /* Mask */ gchar *mask_str = (gchar *) item->getRepr()->attribute("mask"); if ( mask_str ) g_repr->setAttribute("mask", mask_str); /* Clip path */ gchar *clip_path_str = (gchar *) item->getRepr()->attribute("clip-path"); if ( clip_path_str ) g_repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ g_repr->setAttribute("inkscape:transform-center-x", item->getRepr()->attribute("inkscape:transform-center-x"), false); g_repr->setAttribute("inkscape:transform-center-y", item->getRepr()->attribute("inkscape:transform-center-y"), false); /* Whole text's style */ gchar *style_str = sp_style_write_difference(item->style, item->parent->style); g_repr->setAttribute("style", style_str); g_free(style_str); Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); do { Inkscape::Text::Layout::iterator iter_next = iter; iter_next.nextGlyph(); // iter_next is one glyph ahead from iter if (iter == iter_next) break; /* This glyph's style */ SPObject const *pos_obj = 0; void *rawptr = 0; te_get_layout(item)->getSourceOfCharacter(iter, &rawptr); if (!rawptr || !SP_IS_OBJECT(rawptr)) // no source for glyph, abort break; pos_obj = SP_OBJECT(rawptr); while (SP_IS_STRING(pos_obj) && pos_obj->parent) { pos_obj = pos_obj->parent; // SPStrings don't have style } gchar *style_str = sp_style_write_difference(pos_obj->style, pos_obj->parent->style); // get path from iter to iter_next: SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next); iter = iter_next; // shift to next glyph if (!curve) { // error converting this glyph g_free (style_str); continue; } if (curve->is_empty()) { // whitespace glyph? curve->unref(); g_free (style_str); continue; } Inkscape::XML::Node *p_repr = xml_doc->createElement("svg:path"); gchar *def_str = sp_svg_write_path(curve->get_pathvector()); p_repr->setAttribute("d", def_str); g_free(def_str); curve->unref(); p_repr->setAttribute("style", style_str); g_free(style_str); g_repr->appendChild(p_repr); Inkscape::GC::release(p_repr); if (iter == te_get_layout(item)->end()) break; } while (true); return g_repr; } SPCurve *curve = NULL; if (SP_IS_SHAPE(item)) { curve = SP_SHAPE(item)->getCurve(); } if (!curve) return NULL; // Prevent empty paths from being added to the document // otherwise we end up with zomby markup in the SVG file if(curve->is_empty()) { curve->unref(); return NULL; } Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); /* Transformation */ repr->setAttribute("transform", item->getRepr()->attribute("transform")); /* Style */ gchar *style_str = sp_style_write_difference(item->style, item->parent->style); repr->setAttribute("style", style_str); g_free(style_str); /* Mask */ gchar *mask_str = (gchar *) item->getRepr()->attribute("mask"); if ( mask_str ) repr->setAttribute("mask", mask_str); /* Clip path */ gchar *clip_path_str = (gchar *) item->getRepr()->attribute("clip-path"); if ( clip_path_str ) repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ repr->setAttribute("inkscape:transform-center-x", item->getRepr()->attribute("inkscape:transform-center-x"), false); repr->setAttribute("inkscape:transform-center-y", item->getRepr()->attribute("inkscape:transform-center-y"), false); /* Definition */ gchar *def_str = sp_svg_write_path(curve->get_pathvector()); repr->setAttribute("d", def_str); g_free(def_str); curve->unref(); return repr; }
void sp_selected_path_combine(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); SPDocument *doc = sp_desktop_document(desktop); if (g_slist_length((GSList *) selection->itemList()) < 1) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to combine.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Combining paths...")); // set "busy" cursor desktop->setWaitingCursor(); GSList *items = g_slist_copy((GSList *) selection->itemList()); items = sp_degroup_list (items); // descend into any groups in selection GSList *to_paths = NULL; for (GSList *i = items; i != NULL; i = i->next) { SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item) && !SP_IS_GROUP(item)) to_paths = g_slist_prepend(to_paths, item); } GSList *converted = NULL; bool did = sp_item_list_to_curves(to_paths, &items, &converted); g_slist_free(to_paths); for (GSList *i = converted; i != NULL; i = i->next) items = g_slist_prepend(items, doc->getObjectByRepr((Inkscape::XML::Node*)(i->data))); items = sp_degroup_list (items); // converting to path may have added more groups, descend again items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position); items = g_slist_reverse(items); // remember the position, id, transform and style of the topmost path, they will be assigned to the combined one gint position = 0; char const *id = NULL; char const *transform = NULL; char const *style = NULL; char const *path_effect = NULL; SPCurve* curve = NULL; SPItem *first = NULL; Inkscape::XML::Node *parent = NULL; if (did) { selection->clear(); } for (GSList *i = items; i != NULL; i = i->next) { // going from top to bottom SPItem *item = (SPItem *) i->data; if (!SP_IS_PATH(item)) { continue; } if (!did) { selection->clear(); did = true; } SPCurve *c = SP_PATH(item)->get_curve_for_edit(); if (first == NULL) { // this is the topmost path first = item; parent = first->getRepr()->parent(); position = first->getRepr()->position(); id = first->getRepr()->attribute("id"); transform = first->getRepr()->attribute("transform"); // FIXME: merge styles of combined objects instead of using the first one's style style = first->getRepr()->attribute("style"); path_effect = first->getRepr()->attribute("inkscape:path-effect"); //c->transform(item->transform); curve = c; } else { c->transform(item->getRelativeTransform(first)); curve->append(c, false); c->unref(); // reduce position only if the same parent if (item->getRepr()->parent() == parent) { position--; } // delete the object for real, so that its clones can take appropriate action item->deleteObject(); } } g_slist_free(items); if (did) { first->deleteObject(false); // delete the topmost. Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); // restore id, transform, path effect, and style repr->setAttribute("id", id); if (transform) { repr->setAttribute("transform", transform); } repr->setAttribute("style", style); repr->setAttribute("inkscape:path-effect", path_effect); // set path data corresponding to new curve gchar *dstring = sp_svg_write_path(curve->get_pathvector()); curve->unref(); if (path_effect) { repr->setAttribute("inkscape:original-d", dstring); } else { repr->setAttribute("d", dstring); } g_free(dstring); // add the new group to the parent of the topmost parent->appendChild(repr); // move to the position of the topmost, reduced by the number of deleted items repr->setPosition(position > 0 ? position : 0); DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_COMBINE, _("Combine")); selection->set(repr); Inkscape::GC::release(repr); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to combine in the selection.")); } desktop->clearWaitingCursor(); }
bool sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_select, bool skip_all_lpeitems) { bool did = false; for (; items != NULL; items = items->next) { SPItem *item = SP_ITEM(items->data); SPDocument *document = item->document; if ( skip_all_lpeitems && SP_IS_LPE_ITEM(item) && !SP_IS_GROUP(item) ) // also convert objects in an SPGroup when skip_all_lpeitems is set. { continue; } if (SP_IS_PATH(item) && !SP_SHAPE(item)->_curve_before_lpe) { // remove connector attributes if (item->getAttribute("inkscape:connector-type") != NULL) { item->removeAttribute("inkscape:connection-start"); item->removeAttribute("inkscape:connection-end"); item->removeAttribute("inkscape:connector-type"); item->removeAttribute("inkscape:connector-curvature"); did = true; } continue; // already a path, and no path effect } if (SP_IS_BOX3D(item)) { // convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group Inkscape::XML::Node *repr = box3d_convert_to_group(SP_BOX3D(item))->getRepr(); if (repr) { *to_select = g_slist_prepend (*to_select, repr); did = true; *selected = g_slist_remove (*selected, item); } continue; } if (SP_IS_GROUP(item)) { SP_LPE_ITEM(item)->removeAllPathEffects(true); GSList *item_list = sp_item_group_item_list(SP_GROUP(item)); GSList *item_to_select = NULL; GSList *item_selected = NULL; if (sp_item_list_to_curves(item_list, &item_selected, &item_to_select)) did = true; g_slist_free(item_list); g_slist_free(item_to_select); g_slist_free(item_selected); continue; } Inkscape::XML::Node *repr = sp_selected_item_to_curved_repr(item, 0); if (!repr) continue; did = true; *selected = g_slist_remove (*selected, item); // remember the position of the item gint pos = item->getRepr()->position(); // remember parent Inkscape::XML::Node *parent = item->getRepr()->parent(); // remember id char const *id = item->getRepr()->attribute("id"); // remember title gchar *title = item->title(); // remember description gchar *desc = item->desc(); // It's going to resurrect, so we delete without notifying listeners. item->deleteObject(false); // restore id repr->setAttribute("id", id); // add the new repr to the parent parent->appendChild(repr); SPObject* newObj = document->getObjectByRepr(repr); if (title && newObj) { newObj->setTitle(title); g_free(title); } if (desc && newObj) { newObj->setDesc(desc); g_free(desc); } // move to the saved position repr->setPosition(pos > 0 ? pos : 0); /* Buglet: We don't re-add the (new version of the) object to the selection of any other * desktops where it was previously selected. */ *to_select = g_slist_prepend (*to_select, repr); Inkscape::GC::release(repr); } return did; }
void sp_selected_path_break_apart(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); if (selection->isEmpty()) { sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to break apart.")); return; } desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Breaking apart paths...")); // set "busy" cursor desktop->setWaitingCursor(); bool did = false; for (GSList *items = g_slist_copy((GSList *) selection->itemList()); items != NULL; items = items->next) { SPItem *item = (SPItem *) items->data; if (!SP_IS_PATH(item)) { continue; } SPPath *path = SP_PATH(item); SPCurve *curve = path->get_curve_for_edit(); if (curve == NULL) { continue; } did = true; Inkscape::XML::Node *parent = item->getRepr()->parent(); gint pos = item->getRepr()->position(); char const *id = item->getRepr()->attribute("id"); // XML Tree being used directly here while it shouldn't be... gchar *style = g_strdup(item->getRepr()->attribute("style")); // XML Tree being used directly here while it shouldn't be... gchar *path_effect = g_strdup(item->getRepr()->attribute("inkscape:path-effect")); Geom::PathVector apv = curve->get_pathvector() * path->transform; curve->unref(); // it's going to resurrect as one of the pieces, so we delete without advertisement item->deleteObject(false); curve = new SPCurve(apv); g_assert(curve != NULL); GSList *list = curve->split(); curve->unref(); GSList *reprs = NULL; for (GSList *l = list; l != NULL; l = l->next) { curve = (SPCurve *) l->data; Inkscape::XML::Node *repr = parent->document()->createElement("svg:path"); repr->setAttribute("style", style); repr->setAttribute("inkscape:path-effect", path_effect); gchar *str = sp_svg_write_path(curve->get_pathvector()); if (path_effect) repr->setAttribute("inkscape:original-d", str); else repr->setAttribute("d", str); g_free(str); // add the new repr to the parent parent->appendChild(repr); // move to the saved position repr->setPosition(pos > 0 ? pos : 0); // if it's the first one, restore id if (l == list) repr->setAttribute("id", id); reprs = g_slist_prepend (reprs, repr); Inkscape::GC::release(repr); } selection->setReprList(reprs); g_slist_free(reprs); g_slist_free(list); g_free(style); g_free(path_effect); } desktop->clearWaitingCursor(); if (did) { DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_BREAK_APART, _("Break apart")); } else { sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to break apart in the selection.")); } }
static void sp_box3d_drag(Box3DContext &bc, guint /*state*/) { SPDesktop *desktop = SP_EVENT_CONTEXT(&bc)->desktop; if (!bc.item) { if (Inkscape::have_viable_layer(desktop, bc._message_context) == false) { return; } /* Create object */ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(&bc)); Inkscape::XML::Node *repr = xml_doc->createElement("svg:g"); repr->setAttribute("sodipodi:type", "inkscape:box3d"); /* Set style */ sp_desktop_apply_style_tool (desktop, repr, "/tools/shapes/3dbox", false); bc.item = (SPItem *) desktop->currentLayer()->appendChildRepr(repr); Inkscape::GC::release(repr); Inkscape::XML::Node *repr_side; // TODO: Incorporate this in box3d-side.cpp! for (int i = 0; i < 6; ++i) { repr_side = xml_doc->createElement("svg:path"); repr_side->setAttribute("sodipodi:type", "inkscape:box3dside"); repr->addChild(repr_side, NULL); Box3DSide *side = SP_BOX3D_SIDE(inkscape_active_document()->getObjectByRepr (repr_side)); guint desc = Box3D::int_to_face(i); Box3D::Axis plane = (Box3D::Axis) (desc & 0x7); plane = (Box3D::is_plane(plane) ? plane : Box3D::orth_plane_or_axis(plane)); side->dir1 = Box3D::extract_first_axis_direction(plane); side->dir2 = Box3D::extract_second_axis_direction(plane); side->front_or_rear = (Box3D::FrontOrRear) (desc & 0x8); /* Set style */ box3d_side_apply_style(side); SP_OBJECT(side)->updateRepr(); // calls box3d_side_write() and updates, e.g., the axes string description } box3d_set_z_orders(SP_BOX3D(bc.item)); bc.item->updateRepr(); // TODO: It would be nice to show the VPs during dragging, but since there is no selection // at this point (only after finishing the box), we must do this "manually" /* bc._vpdrag->updateDraggers(); */ desktop->canvas->force_full_redraw_after_interruptions(5); } g_assert(bc.item); SPBox3D *box = SP_BOX3D(bc.item); box->orig_corner0 = bc.drag_origin_proj; box->orig_corner7 = bc.drag_ptC_proj; box3d_check_for_swapped_coords(box); /* we need to call this from here (instead of from box3d_position_set(), for example) because z-order setting must not interfere with display updates during undo/redo */ box3d_set_z_orders (box); box3d_position_set(box); // status text bc._message_context->setF(Inkscape::NORMAL_MESSAGE, "%s", _("<b>3D Box</b>; with <b>Shift</b> to extrude along the Z axis")); }
SPItem *SPUse::unlink() { Inkscape::XML::Node *repr = this->getRepr(); if (!repr) { return NULL; } Inkscape::XML::Node *parent = repr->parent(); SPDocument *document = this->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); // Track the ultimate source of a chain of uses. SPItem *orig = this->root(); if (!orig) { return NULL; } // Calculate the accumulated transform, starting from the original. Geom::Affine t = this->get_root_transform(); Inkscape::XML::Node *copy = NULL; if (dynamic_cast<SPSymbol *>(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) { Inkscape::XML::Node *newchild = child->duplicate(xml_doc); copy->appendChild(newchild); } } else { // just copy copy = orig->getRepr()->duplicate(xml_doc); } // Add the duplicate repr just after the existing one. parent->addChild(copy, repr); // Retrieve the SPItem of the resulting repr. SPObject *unlinked = document->getObjectByRepr(copy); // Merge style from the use. unlinked->style->merge( this->style ); unlinked->style->cascade( unlinked->parent->style ); unlinked->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(this, NULL); Inkscape::GC::anchor(repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. this->deleteObject(false); // Give the copy our old id and let go of our old repr. copy->setAttribute("id", repr->attribute("id")); Inkscape::GC::release(repr); // Remove tiled clone attrs. copy->setAttribute("inkscape:tiled-clone-of", NULL); copy->setAttribute("inkscape:tile-w", NULL); copy->setAttribute("inkscape:tile-h", NULL); copy->setAttribute("inkscape:tile-cx", NULL); copy->setAttribute("inkscape:tile-cy", NULL); // Establish the succession and let go of our object. this->setSuccessor(unlinked); sp_object_unref(this, NULL); SPItem *item = dynamic_cast<SPItem *>(unlinked); g_assert(item != NULL); // Set the accummulated transform. { Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. item->doWriteTransform(item->getRepr(), t, &nomove); } return item; }
SPDocument * sp_document_create(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, gchar const *name, unsigned int keepalive) { SPDocument *document; Inkscape::XML::Node *rroot; Inkscape::Version sodipodi_version; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); rroot = rdoc->root(); document = new SPDocument(); document->keepalive = keepalive; document->rdoc = rdoc; document->rroot = rroot; #ifndef WIN32 prepend_current_dir_if_relative(&(document->uri), uri); #else // FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test! document->uri = uri? g_strdup(uri) : NULL; #endif // base is simply the part of the path before filename; e.g. when running "inkscape ../file.svg" the base is "../" // which is why we use g_get_current_dir() in calculating the abs path above //This is NULL for a new document if (base) document->base = g_strdup(base); else document->base = NULL; document->name = g_strdup(name); document->root = sp_object_repr_build_tree(document, rroot); sodipodi_version = SP_ROOT(document->root)->version.sodipodi; /* fixme: Not sure about this, but lets assume ::build updates */ rroot->setAttribute("sodipodi:version", SODIPODI_VERSION); rroot->setAttribute("inkscape:version", Inkscape::version_string); /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */ /* Quick hack 2 - get default image size into document */ if (!rroot->attribute("width")) rroot->setAttribute("width", "100%"); if (!rroot->attribute("height")) rroot->setAttribute("height", "100%"); /* End of quick hack 2 */ /* Quick hack 3 - Set uri attributes */ if (uri) { rroot->setAttribute("sodipodi:docname", uri); } /* End of quick hack 3 */ /* Eliminate obsolete sodipodi:docbase, for privacy reasons */ rroot->setAttribute("sodipodi:docbase", NULL); /* Eliminate any claim to adhere to a profile, as we don't try to */ rroot->setAttribute("baseProfile", NULL); // creating namedview if (!sp_item_group_get_child_by_name((SPGroup *) document->root, NULL, "sodipodi:namedview")) { // if there's none in the document already, Inkscape::XML::Node *rnew = NULL; rnew = rdoc->createElement("sodipodi:namedview"); //rnew->setAttribute("id", "base"); // Add namedview data from the preferences // we can't use getAllEntries because this could produce non-SVG doubles Glib::ustring pagecolor = prefs->getString("/template/base/pagecolor"); if (!pagecolor.empty()) { rnew->setAttribute("pagecolor", pagecolor.data()); } Glib::ustring bordercolor = prefs->getString("/template/base/bordercolor"); if (!bordercolor.empty()) { rnew->setAttribute("bordercolor", bordercolor.data()); } sp_repr_set_svg_double(rnew, "borderopacity", prefs->getDouble("/template/base/borderopacity", 1.0)); sp_repr_set_svg_double(rnew, "objecttolerance", prefs->getDouble("/template/base/objecttolerance", 10.0)); sp_repr_set_svg_double(rnew, "gridtolerance", prefs->getDouble("/template/base/gridtolerance", 10.0)); sp_repr_set_svg_double(rnew, "guidetolerance", prefs->getDouble("/template/base/guidetolerance", 10.0)); sp_repr_set_svg_double(rnew, "inkscape:pageopacity", prefs->getDouble("/template/base/inkscape:pageopacity", 0.0)); sp_repr_set_int(rnew, "inkscape:pageshadow", prefs->getInt("/template/base/inkscape:pageshadow", 2)); sp_repr_set_int(rnew, "inkscape:window-width", prefs->getInt("/template/base/inkscape:window-width", 640)); sp_repr_set_int(rnew, "inkscape:window-height", prefs->getInt("/template/base/inkscape:window-height", 480)); // insert into the document rroot->addChild(rnew, NULL); // clean up Inkscape::GC::release(rnew); } /* Defs */ if (!SP_ROOT(document->root)->defs) { Inkscape::XML::Node *r; r = rdoc->createElement("svg:defs"); rroot->addChild(r, NULL); Inkscape::GC::release(r); g_assert(SP_ROOT(document->root)->defs); } /* Default RDF */ rdf_set_defaults( document ); if (keepalive) { inkscape_ref(); } // Remark: Here, we used to create a "currentpersp3d" element in the document defs. // But this is probably a bad idea since we need to adapt it for every change of selection, which will // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup? document->current_persp3d = persp3d_document_first_persp(document); if (!document->current_persp3d) { document->current_persp3d = persp3d_create_xml_element (document); } sp_document_set_undo_sensitive(document, true); // reset undo key when selection changes, so that same-key actions on different objects are not coalesced if (!Inkscape::NSApplication::Application::getNewGui()) { g_signal_connect(G_OBJECT(INKSCAPE), "change_selection", G_CALLBACK(sp_document_reset_key), document); g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(sp_document_reset_key), document); } else { document->_selection_changed_connection = Inkscape::NSApplication::Editor::connectSelectionChanged (sigc::mem_fun (*document, &SPDocument::reset_key)); document->_desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*document, &SPDocument::reset_key)); } return document; }